﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using Microsoft.VisualBasic;
using System.Drawing;
using System.Diagnostics;
using System.Reflection;
using System.Security;
using System.Net;
using System.Web;
using System.IO;
using System.Threading;
using System.Net.Sockets;
using System.Globalization;
using Microsoft.Win32;
using System.Runtime.CompilerServices;

using LongNet.Security;

namespace LongNet.Util
{
    public static class Utils
    {
        #region Fields

        private static readonly Regex StringToPinyinRegex = new Regex(@"^[\u4e00-\u9fa5]$", RegexOptions.IgnoreCase);

        private static readonly Regex StringFromUnicodeRegex = new Regex(@"(\\u\w{4})", RegexOptions.Singleline | RegexOptions.IgnoreCase);
        private static readonly MatchEvaluator StringFromUnicodeEvaluator = new MatchEvaluator((Match m) =>
        {
            char[] ch = m.Groups[1].Value.ToCharArray();

            byte[] bytes = new byte[2];
            bytes[1] = Constants.HexStringIndexTable[new string(new char[2] { ch[2], ch[3] })];
            bytes[0] = Constants.HexStringIndexTable[new string(new char[2] { ch[4], ch[5] })];

            return Encoding.Unicode.GetString(bytes);
        });


        private static string hostName;
        private static string appFriendlyName;
        private static DateTime processStartTime = DateTime.MinValue;
        #endregion Fields

        #region Properties

        /// <summary>
        /// Gets the system dependent line terminator.
        /// </summary>
        /// <value>
        /// The system dependent line terminator.
        /// </value>
        public static string NewLine
        {
            get
            {
                return Environment.NewLine;
            }
        }

        /// <summary>
        /// Gets the base directory for current <see cref="AppDomain"/>.
        /// </summary>
        /// <value>The base directory path for the current <see cref="AppDomain"/>.</value>
        public static string AppBaseDirectory
        {
            get
            {
                return AppDomain.CurrentDomain.BaseDirectory;
            }
        }

        /// <summary>
        /// Gets the path to the configuration file for the current <see cref="AppDomain"/>.
        /// </summary>
        /// <value>The path to the configuration file for the current <see cref="AppDomain"/>.</value>
        /// <remarks>
        /// <para>
        /// The .NET Compact Framework 1.0 does not have a concept of a configuration
        /// file. For this runtime, we use the entry assembly location as the root for
        /// the configuration file name.
        /// </para>
        /// <para>
        /// The value returned may be either a local file path or a URI.
        /// </para>
        /// </remarks>
        public static string AppConfigurationFile
        {
            get
            {
                return AppDomain.CurrentDomain.SetupInformation.ConfigurationFile;
            }
        }

        /// <summary>
        /// Gets the path to the file that first executed in the current <see cref="AppDomain"/>.
        /// </summary>
        /// <value>The path to the entry assembly.</value>
        /// <remarks>
        /// <para>
        /// Gets the path to the file that first executed in the current <see cref="AppDomain"/>.
        /// </para>
        /// </remarks>
        public static string EntryAssemblyLocation
        {
            get
            {
                return Assembly.GetEntryAssembly().Location;
            }
        }

        /// <summary>
        /// Gets the ID of the current thread.
        /// </summary>
        /// <value>The ID of the current thread.</value>
        /// <remarks>
        /// <para>
        /// On the .NET framework, the <c>AppDomain.GetCurrentThreadId</c> method
        /// is used to obtain the thread ID for the current thread. This is the 
        /// operating system ID for the thread.
        /// </para>
        /// <para>
        /// On the .NET Compact Framework 1.0 it is not possible to get the 
        /// operating system thread ID for the current thread. The native method 
        /// <c>GetCurrentThreadId</c> is implemented inline in a header file
        /// and cannot be called.
        /// </para>
        /// </remarks>
        public static int CurrentThreadId
        {
            get
            {
                return Thread.CurrentThread.ManagedThreadId;
            }
        }

        /// <summary>
        /// Get the host name or machine name for the current machine
        /// </summary>
        /// <value>
        /// The hostname or machine name
        /// </value>
        /// <remarks>
        /// <para>
        /// Get the host name or machine name for the current machine
        /// </para>
        /// <para>
        /// The host name (<see cref="System.Net.Dns.GetHostName"/>) or
        /// the machine name (<c>Environment.MachineName</c>) for
        /// the current machine, or if neither of these are available
        /// then <c>NOT AVAILABLE</c> is returned.
        /// </para>
        /// </remarks>
        public static string HostName
        {
            get
            {
                if (hostName == null)
                {
                    // Get the DNS host name of the current machine
                    try
                    {
                        // Lookup the host name
                        hostName = Dns.GetHostName();
                    }
                    catch (SocketException)
                    {
                    }
                    catch (SecurityException)
                    {
                        // We may get a security exception looking up the hostname
                        // You must have Unrestricted DnsPermission to access resource
                    }

                    // Get the NETBIOS machine name of the current machine
                    if (hostName == null || hostName.Length == 0)
                    {
                        try
                        {
                            hostName = Environment.MachineName;
                        }
                        catch (InvalidOperationException)
                        {
                        }
                        catch (SecurityException)
                        {
                            // We may get a security exception looking up the machine name
                            // You must have Unrestricted EnvironmentPermission to access resource
                        }
                    }

                    // Couldn't find a value
                    if (hostName == null || hostName.Length == 0)
                    {
                        hostName = "NOT AVAILABLE";
                    }
                }

                return hostName;
            }
        }

        /// <summary>
        /// Get this application's friendly name
        /// </summary>
        /// <value>
        /// The friendly name of this application as a string
        /// </value>
        /// <remarks>
        /// <para>
        /// If available the name of the application is retrieved from
        /// the <c>AppDomain</c> using <c>AppDomain.CurrentDomain.FriendlyName</c>.
        /// </para>
        /// <para>
        /// Otherwise the file name of the entry assembly is used.
        /// </para>
        /// </remarks>
        public static string AppFriendlyName
        {
            get
            {
                if (appFriendlyName == null)
                {
                    try
                    {
                        appFriendlyName = AppDomain.CurrentDomain.FriendlyName;
                    }
                    catch (SecurityException)
                    {
                        // This security exception will occur if the caller does not have 
                        // some undefined set of SecurityPermission flags.
                    }

                    if (appFriendlyName == null || appFriendlyName.Length == 0)
                    {
                        try
                        {
                            string assemblyLocation = Utils.EntryAssemblyLocation;
                            appFriendlyName = Path.GetFileName(assemblyLocation);
                        }
                        catch (SecurityException)
                        {
                            // Caller needs path discovery permission
                        }
                    }

                    if (appFriendlyName == null || appFriendlyName.Length == 0)
                    {
                        appFriendlyName = "NOT AVAILABLE";
                    }
                }

                return appFriendlyName;
            }
        }

        /// <summary>
        /// Get the start time for the current process.
        /// </summary>
        /// <remarks>
        /// <para>
        /// Tries to get the start time for the current process.
        /// Failing that it returns the time of the first call to
        /// this property.
        /// </para>
        /// <para>
        /// Note that AppDomains may be loaded and unloaded within the
        /// same process without the process terminating and therefore
        /// without the process start time being reset.
        /// </para>
        /// </remarks>
        public static DateTime ProcessStartTime
        {
            get
            {
                if (processStartTime == DateTime.MinValue)
                {
                    try
                    {
                        processStartTime = Process.GetCurrentProcess().StartTime;
                    }
                    catch
                    {
                        // Unable to get the start time, use now as the start time
                        processStartTime = DateTime.Now;
                    }
                }

                return processStartTime;
            }
        }

        #endregion

        #region Constructor
        #endregion Public Static Properties

        #region StringToBytes

        /// <summary>
        /// Gets a sequence of bytes encoded from all the characters in the specified string, 
        /// using an encoding for the ASCII (7-bit) character set.
        /// </summary>
        /// <param name="str">The string to encode.</param>
        /// <returns>A byte array containing the results of encoding the specified set of characters.</returns>
        public static byte[] GetASCIIBytes(string str)
        {
            return Encoding.ASCII.GetBytes(str);
        }

        /// <summary>
        /// Gets a sequence of bytes encoded from all the characters in the specified string, 
        /// using an encoding for the UTF-16 format using the little endian byte order.
        /// </summary>
        /// <param name="str">The string to encode.</param>
        /// <returns>A byte array containing the results of encoding the specified set of characters.</returns>
        public static byte[] GetUnicodeBytes(string str)
        {
            return Encoding.Unicode.GetBytes(str);
        }

        /// <summary>
        /// Gets a sequence of bytes encoded from all the characters in the specified string, 
        /// using an encoding for the UTF-32 format using the little endian byte order.
        /// </summary>
        /// <param name="str">The string to encode.</param>
        /// <returns>A byte array containing the results of encoding the specified set of characters.</returns>
        public static byte[] GetUTF32Bytes(string str)
        {
            return Encoding.UTF32.GetBytes(str);
        }

        /// <summary>
        /// Gets a sequence of bytes encoded from all the characters in the specified string, 
        /// using an encoding for the UTF-7 format.
        /// </summary>
        /// <param name="str">The string to encode.</param>
        /// <returns>A byte array containing the results of encoding the specified set of characters.</returns>
        public static byte[] GetUTF7Bytes(string str)
        {
            return Encoding.UTF7.GetBytes(str);
        }

        /// <summary>
        /// Gets a sequence of bytes encoded from all the characters in the specified string, 
        /// using an encoding for the UTF-8 format.
        /// </summary>
        /// <param name="str">The string to encode.</param>
        /// <returns>A byte array containing the results of encoding the specified set of characters.</returns>
        public static byte[] GetUTF8Bytes(string str)
        {
            return Encoding.UTF8.GetBytes(str);
        }


        /// <summary>
        /// Gets a sequence of bytes encoded from all the characters in the specified string, 
        /// using an encoding for the operating system's current ANSI code page.
        /// </summary>
        /// <param name="str">The string to encode.</param>
        /// <returns>A byte array containing the results of encoding the specified set of characters.</returns>
        public static byte[] GetBytes(string str)
        {
            return Encoding.Default.GetBytes(str);
        }

        /// <summary>
        /// Gets a sequence of bytes encoded from all the characters in the specified string.
        /// </summary>
        /// <param name="str">The string to encode.</param>
        /// <param name="encoding">An <see cref="Encoding"/> object.</param>
        /// <returns>A byte array containing the results of encoding the specified set of characters.</returns>
        public static byte[] GetBytes(string str, Encoding encoding)
        {
            return encoding.GetBytes(str);
        }

        /// <summary>
        /// Gets a sequence of bytes encoded from all the characters in the specified string.
        /// </summary>
        /// <param name="str">The string to encode.</param>
        /// <param name="encodingName">The name of an <see cref="Encoding"/>.</param>
        /// <returns>A byte array containing the results of encoding the specified set of characters.</returns>
        public static byte[] GetBytes(string str, string encodingName)
        {
            return Encoding.GetEncoding(encodingName).GetBytes(str);
        }

        /// <summary>
        /// Gets a 32-bit integer that represents the bytes length of a sequence of bytes encoded from all 
        /// the characters in the specified string, using an encoding for the operating system's current ANSI code page.
        /// </summary>
        /// <param name="str">The string to encode.</param>
        /// <returns>A byte array containing the results of encoding the specified set of characters.</returns>
        public static int GetBytesLength(string str)
        {
            return Encoding.Default.GetBytes(str).Length;
        }

        /// <summary>
        /// Gets a 64-bit integer that represents the bytes length of a sequence of bytes encoded from all 
        /// the characters in the specified string, using an encoding for the operating system's current ANSI code page.
        /// </summary>
        /// <param name="str">The string to encode.</param>
        /// <returns>A byte array containing the results of encoding the specified set of characters.</returns>
        public static long GetBytesLongLength(string str)
        {
            return Encoding.Default.GetBytes(str).LongLength;
        }

        #endregion

        #region BytesToString

        /// <summary>
        /// Gets a string encoded from all the bytes in the specified byte array, 
        /// using an encoding for the ASCII (7-bit) character set.
        /// </summary>
        /// <param name="bytes">The byte array containing the sequence of bytes to decode.</param>
        /// <returns>A string containing the results of decoding the specified sequence of bytes.</returns>
        public static string GetASCIIString(byte[] bytes)
        {
            return Encoding.ASCII.GetString(bytes);
        }

        /// <summary>
        /// Gets a string encoded from all the bytes in the specified byte array, 
        /// using an encoding for the UTF-16 format using the little endian byte order.
        /// </summary>
        /// <param name="bytes">The byte array containing the sequence of bytes to decode.</param>
        /// <returns>A string containing the results of decoding the specified sequence of bytes.</returns>
        public static string GetUnicodeString(byte[] bytes)
        {
            return Encoding.Unicode.GetString(bytes);
        }

        /// <summary>
        /// Gets a string encoded from all the bytes in the specified byte array, 
        /// using an encoding for the UTF-32 format using the little endian byte order.
        /// </summary>
        /// <param name="bytes">The byte array containing the sequence of bytes to decode.</param>
        /// <returns>A string containing the results of decoding the specified sequence of bytes.</returns>
        public static string GetUTF32String(byte[] bytes)
        {
            return Encoding.UTF32.GetString(bytes);
        }

        /// <summary>
        /// Gets a string encoded from all the bytes in the specified byte array, 
        /// using an encoding for the UTF-7 format.
        /// </summary>
        /// <param name="bytes">The byte array containing the sequence of bytes to decode.</param>
        /// <returns>A string containing the results of decoding the specified sequence of bytes.</returns>
        public static string GetUTF7String(byte[] bytes)
        {
            return Encoding.UTF7.GetString(bytes);
        }

        /// <summary>
        /// Gets a string encoded from all the bytes in the specified byte array, 
        /// using an encoding for the UTF-8 format.
        /// </summary>
        /// <param name="bytes">The byte array containing the sequence of bytes to decode.</param>
        /// <returns>A string containing the results of decoding the specified sequence of bytes.</returns>
        public static string GetUTF8String(byte[] bytes)
        {
            return Encoding.UTF8.GetString(bytes);
        }


        /// <summary>
        /// Gets a string encoded from all the bytes in the specified byte array, 
        /// using an encoding for the operating system's current ANSI code page.
        /// </summary>
        /// <param name="bytes">The byte array containing the sequence of bytes to decode.</param>
        /// <returns>A string containing the results of decoding the specified sequence of bytes.</returns>
        public static string GetString(byte[] bytes)
        {
            return Encoding.Default.GetString(bytes);
        }

        /// <summary>
        /// Gets a string encoded from all the bytes in the specified byte array.
        /// </summary>
        /// <param name="bytes">The byte array containing the sequence of bytes to decode.</param>
        /// <param name="encoding">An <see cref="Encoding"/> object.</param>
        /// <returns>A string containing the results of decoding the specified sequence of bytes.</returns>
        public static string GetString(byte[] bytes, Encoding encoding)
        {
            return encoding.GetString(bytes);
        }

        /// <summary>
        /// Gets a string encoded from all the bytes in the specified byte array.
        /// </summary>
        /// <param name="bytes">The byte array containing the sequence of bytes to decode.</param>
        /// <param name="encodingName">The name of an <see cref="Encoding"/>.</param>
        /// <returns>A string containing the results of decoding the specified sequence of bytes.</returns>
        public static string GetString(byte[] bytes, string encodingName)
        {
            return Encoding.GetEncoding(encodingName).GetString(bytes);
        }

        #endregion

        #region StringTo(value types)

        /// <summary>
        /// Convert string to bool.
        /// If fail to convert, false will be returned.
        /// </summary>
        /// <param name="str">The string to convert.</param>
        /// <returns>The converted bool value.</returns>
        public static bool StringToBool(string str)
        {
            return StringToBool(str, false);
        }
        /// <summary>
        /// Convert string to bool.
        /// </summary>
        /// <param name="str">The string to convert.</param>
        /// <param name="defaultValue">If fail to convert, defaultValue will be returned.</param>
        /// <returns>The converted bool value.</returns>
        public static bool StringToBool(string str, bool defaultValue)
        {
            bool.TryParse(str == null ? string.Empty : str.Split(',')[0], out defaultValue);
            return defaultValue;
        }

        /// <summary>
        /// Convert string to byte.
        /// If fail to convert, 0 will be returned.
        /// </summary>
        /// <param name="str">The string to convert.</param>
        /// <returns>The converted byte value.</returns>
        public static byte StringToByte(string str)
        {
            return StringToByte(str, 0);
        }
        /// <summary>
        /// Convert string to byte.
        /// </summary>
        /// <param name="str">The string to convert.</param>
        /// <param name="defaultValue">If fail to convert, defaultValue will be returned.</param>
        /// <returns>The converted byte value.</returns>
        public static byte StringToByte(string str, byte defaultValue)
        {
            byte.TryParse(str, out defaultValue);
            return defaultValue;
        }

        /// <summary>
        /// Convert string to int.
        /// If fail to convert, 0 will be returned.
        /// </summary>
        /// <param name="str">The string to convert.</param>
        /// <returns>The converted int value.</returns>
        public static int StringToInt(string str)
        {
            return StringToInt(str, 0);
        }
        /// <summary>
        /// Convert string to int.
        /// </summary>
        /// <param name="str">The string to convert.</param>
        /// <param name="defaultValue">If fail to convert, defaultValue will be returned.</param>
        /// <returns>The converted int value.</returns>
        public static int StringToInt(string str, int defaultValue)
        {
            int.TryParse(str, out defaultValue);
            return defaultValue;
        }

        /// <summary>
        /// Convert string to long.
        /// If fail to convert, 0 will be returned.
        /// </summary>
        /// <param name="str">The string to convert.</param>
        /// <returns>The converted long value.</returns>
        public static long StringToLong(string str)
        {
            return StringToLong(str, 0);
        }
        /// <summary>
        /// Convert string to long.
        /// </summary>
        /// <param name="str">The string to convert.</param>
        /// <param name="defaultValue">If fail to convert, defaultValue will be returned.</param>
        /// <returns>The converted long value.</returns>
        public static long StringToLong(string str, long defaultValue)
        {
            long.TryParse(str, out defaultValue);
            return defaultValue;
        }

        /// <summary>
        /// Convert string to float.
        /// If fail to convert, 0 will be returned.
        /// </summary>
        /// <param name="str">The string to convert.</param>
        /// <returns>The converted float value.</returns>
        public static float StringToFloat(string str)
        {
            return StringToFloat(str, 0F);
        }
        /// <summary>
        /// Convert string to float.
        /// </summary>
        /// <param name="str">The string to convert.</param>
        /// <param name="defaultValue">If fail to convert, defaultValue will be returned.</param>
        /// <returns>The converted float value.</returns>
        public static float StringToFloat(string str, float defaultValue)
        {
            float.TryParse(str, out defaultValue);
            return defaultValue;
        }

        /// <summary>
        /// Convert string to double.
        /// If fail to convert, 0 will be returned.
        /// </summary>
        /// <param name="str">The string to convert.</param>
        /// <returns>The converted double value.</returns>
        public static double StringToDouble(string str)
        {
            return StringToDouble(str, 0D);
        }
        /// <summary>
        /// Convert string to double.
        /// </summary>
        /// <param name="str">The string to convert.</param>
        /// <param name="defaultValue">If fail to convert, defaultValue will be returned.</param>
        /// <returns>The converted double value.</returns>
        public static double StringToDouble(string str, double defaultValue)
        {
            double.TryParse(str, out defaultValue);
            return defaultValue;
        }

        /// <summary>
        /// Convert string to decimal.
        /// If fail to convert, 0 will be returned.
        /// </summary>
        /// <param name="str">The string to convert.</param>
        /// <returns>The converted decimal value.</returns>
        public static decimal StringToDecimal(string str)
        {
            return StringToDecimal(str, 0M);
        }
        /// <summary>
        /// Convert string to decimal.
        /// </summary>
        /// <param name="str">The string to convert.</param>
        /// <param name="defaultValue">If fail to convert, defaultValue will be returned.</param>
        /// <returns>The converted decimal value.</returns>
        public static decimal StringToDecimal(string str, decimal defaultValue)
        {
            decimal.TryParse(str, out defaultValue);
            return defaultValue;
        }

        /// <summary>
        /// Convert string to DateTime.
        /// If fail to convert, DateTime.MinValue will be returned.
        /// </summary>
        /// <param name="str">The string to convert.</param>
        /// <returns>The converted DateTime value.</returns>
        public static DateTime StringToDateTime(string str)
        {
            return StringToDateTime(str, DateTime.MinValue);
        }
        /// <summary>
        /// Convert string to DateTime.
        /// </summary>
        /// <param name="str">The string to convert.</param>
        /// <param name="defaultValue">If fail to convert, defaultValue will be returned.</param>
        /// <returns>The converted DateTime value.</returns>
        public static DateTime StringToDateTime(string str, DateTime defaultValue)
        {
            DateTime.TryParse(str, out defaultValue);
            return defaultValue;
        }

        /// <summary>
        /// Convert string to DateTime.
        /// If fail to convert, <seealso cref="F:Guid.Empty"/> will be returned.
        /// </summary>
        /// <param name="str">The string to convert.</param>
        /// <returns>The converted Guid value.</returns>
        public static Guid StringToGuid(string str)
        {
            return StringToGuid(str, Guid.Empty);
        }
        /// <summary>
        /// Convert string to DateTime.
        /// If fail to convert, <paramref name="defaultValue"/> will be returned.
        /// </summary>
        /// <param name="str">The string to convert.</param>
        /// <param name="defaultValue">If fail to convert, defaultValue will be returned.</param>
        /// <returns>The converted Guid value.</returns>
        public static Guid StringToGuid(string str, Guid defaultValue)
        {
            try
            {
                return new Guid(str);
            }
            catch
            {
                return defaultValue;
            }
        }

        /// <summary>
        /// Converts a string to the specified enum value, ignore case.
        /// </summary>
        /// <typeparam name="T">An enum type.</typeparam>
        /// <param name="str">The string to convert.</param>
        /// <param name="defaultValue">If fail to convert, this value will be returned.</param>
        /// <returns>The converted value.</returns>
        public static T StringToEnum<T>(string str, T defaultValue)
        {
            return StringToEnum<T>(str, defaultValue, true);
        }

        /// <summary>
        /// Converts a string to the specified enum value.
        /// </summary>
        /// <typeparam name="T">An enum type.</typeparam>
        /// <param name="str">The string to convert.</param>
        /// <param name="defaultValue">If fail to convert, this value will be returned.</param>
        /// <param name="ignoreCase">If true, ignore case; otherwise, regard case.</param>
        /// <returns>The converted value.</returns>
        public static T StringToEnum<T>(string str, T defaultValue, bool ignoreCase)
        {
            try
            {
                return (T)Enum.Parse(typeof(T), str, ignoreCase);
            }
            catch
            {
                return defaultValue;
            }
        }

        #endregion

        #region StringTo(other case)

        /// <summary>
        /// Converts a string to Camel Casing(the first character to lower case).
        /// </summary>
        /// <remarks>Camel Casing convention capitalizes the first character of each word except the first word.</remarks>
        /// <param name="str">A <see cref="System.String"/> reference.</param>
        /// <returns>A Camel Casing string.</returns>
        public static string StringToCamelCase(string str)
        {
            if (string.IsNullOrEmpty(str) || char.IsLower(str[0]))
                return str;

            return char.ToLower(str[0]).ToString() + str.Substring(1);
        }

        /// <summary>
        /// Converts a string to Pascal Casing(the first character to upper case).
        /// </summary>
        /// <remarks>Pascal Casing convention capitalizes the first character of each word (including acronyms over two letters in length).</remarks>
        /// <param name="str">A <see cref="System.String"/> reference.</param>
        /// <returns>A Pascal Casing string.</returns>
        public static string StringToPascalCase(string str)
        {
            if (string.IsNullOrEmpty(str) || char.IsUpper(str[0]))
                return str;

            return char.ToUpper(str[0]).ToString() + str.Substring(1);
        }

        /// <summary>
        /// Converts a string to SBC case.
        /// </summary>
        /// <param name="str">The string to convert.</param>
        /// <returns>The converted SBC case string.</returns>
        public static string StringToSbcCase(string str)
        {
            char[] c = str.ToCharArray();

            for (int i = 0; i < c.Length; i++)
            {
                if (c[i] == 32)
                {
                    c[i] = (char)12288;
                    continue;
                }
                if (c[i] < 127)
                {
                    c[i] = (char)(c[i] + 65248);
                }
            }
            //char[] c = str.ToCharArray();
            //for (int i = 0; i < c.Length; i++)
            //{
            //    byte[] b = System.Text.Encoding.Unicode.GetBytes(c, i, 1);
            //    if (b.Length == 2)
            //    {
            //        if (b[1] == 0)
            //        {
            //            b[0] = (byte)(b[0] - 32);
            //            b[1] = 255;
            //            c[i] = System.Text.Encoding.Unicode.GetChars(b)[0];
            //        }
            //    }
            //}

            return (new string(c));
        }

        /// <summary>
        /// Converts a string to DBC case.
        /// </summary>
        /// <param name="str">The string to convert.</param>
        /// <returns>The converted DBC case string.</returns>
        public static string StringToDbcCase(string str)
        {
            char[] c = str.ToCharArray();

            for (int i = 0; i < c.Length; i++)
            {
                if (c[i] == 12288)
                {
                    c[i] = (char)32;
                    continue;
                }
                if (c[i] > 65280 && c[i] < 65375)
                {
                    c[i] = (char)(c[i] - 65248);
                }
            }

            //char[] c = str.ToCharArray();
            //for (int i = 0; i < c.Length; i++)
            //{
            //    byte[] b = System.Text.Encoding.Unicode.GetBytes(c, i, 1);
            //    if (b.Length == 2)
            //    {
            //        if (b[1] == 255)
            //        {
            //            b[0] = (byte)(b[0] + 32);
            //            b[1] = 0;
            //            c[i] = System.Text.Encoding.Unicode.GetChars(b)[0];
            //        }
            //    }
            //}

            return (new string(c));
        }

        /// <summary>
        /// Converts a string to proper case(first letter to upper case for each word).
        /// </summary>
        /// <param name="str">The string to convert.</param>
        /// <returns>The converted proper case string.</returns>
        public static string StringToProperCase(string str)
        {
            StringBuilder sb = new StringBuilder();
            bool empty = true;
            foreach (char c in str)
            {
                char ch = c;
                if (char.IsWhiteSpace(ch))
                    empty = true;
                else
                {
                    if (empty && char.IsLetter(ch))
                        ch = char.ToUpper(ch);
                    else
                        ch = char.ToLower(ch);
                    empty = false;
                }
                sb.Append(ch);
            }
            return sb.ToString();
        }

        /// <summary>
        /// Converts a string to unicode.
        /// </summary>
        /// <param name="str">The string to convert.</param>
        /// <returns>The converted unicode string.</returns>
        public static string StringToUnicode(string str)
        {
            StringBuilder sb = new StringBuilder();
            char[] ch = str.ToCharArray();

            for (int i = 0; i < ch.Length; i++)
            {
                byte[] bytes = Encoding.Unicode.GetBytes(ch[i].ToString());
                sb.Append(@"\u" + bytes[1].ToString("X2") + bytes[0].ToString("X2"));
            }

            return sb.ToString();
        }

        /// <summary>
        /// Converts a unicode string to original string.
        /// </summary>
        /// <param name="str">The unicode string to convert.</param>
        /// <returns>The converted original string.</returns>
        public static string StringFromUnicode(string str)
        {
            //StringBuilder sb = new StringBuilder();

            //char[] ch = str.ToCharArray();
            //int count = ch.Length / 6;
            //for (int i = 0; i < count; i++)
            //{
            //    int index = i * 6;
            //    byte[] bytes = new byte[2];
            //    bytes[1] = Constants.HexStringIndexTable[new string(new char[2] { ch[index + 2], ch[index + 3] })];
            //    bytes[0] = Constants.HexStringIndexTable[new string(new char[2] { ch[index + 4], ch[index + 5] })];
            //    sb.Append(Encoding.Unicode.GetString(bytes));
            //}

            //return sb.ToString();

            return StringFromUnicodeRegex.Replace(str, StringFromUnicodeEvaluator);
        }

        /// <summary>
        /// Converts a string to <see cref="Color"/> object.
        /// </summary>
        /// <param name="color">A string represents a color(e.g. #fff).</param>
        /// <returns>The converted <see cref="Color"/> object.</returns>
        public static Color StringToColor(string color)
        {
            char[] rgb;
            int red, green, blue = 0;
            color = color.TrimStart('#');
            color = Regex.Replace(color.ToLower(), "[g-zG-Z]", "");
            switch (color.Length)
            {
                case 3:
                    rgb = color.ToCharArray();
                    red = Convert.ToInt32(rgb[0].ToString() + rgb[0].ToString(), 16);
                    green = Convert.ToInt32(rgb[1].ToString() + rgb[1].ToString(), 16);
                    blue = Convert.ToInt32(rgb[2].ToString() + rgb[2].ToString(), 16);
                    return Color.FromArgb(red, green, blue);
                case 6:
                    rgb = color.ToCharArray();
                    red = Convert.ToInt32(rgb[0].ToString() + rgb[1].ToString(), 16);
                    green = Convert.ToInt32(rgb[2].ToString() + rgb[3].ToString(), 16);
                    blue = Convert.ToInt32(rgb[4].ToString() + rgb[5].ToString(), 16);
                    return Color.FromArgb(red, green, blue);
                default:
                    return Color.FromName(color);
            }
        }


        /// <summary>
        /// Converts a string to simplified chinese.
        /// </summary>
        /// <param name="str">The string to convert.</param>
        /// <returns>The converted simplified chinese string.</returns>
        public static string StringToSimplifiedChinese(string str)
        {
            return Strings.StrConv(str, VbStrConv.SimplifiedChinese, 0x0009);
        }

        /// <summary>
        /// Converts a string to traditional chinese.
        /// </summary>
        /// <param name="str">The string to convert.</param>
        /// <returns>The converted traditional chinese string.</returns>
        public static string StringToTraditionalChinese(string str)
        {
            return Strings.StrConv(str, VbStrConv.TraditionalChinese, 0x0009);
        }

        /// <summary>
        /// Converts a chinese string to spell string.
        /// </summary>
        /// <param name="str">The string to convert.</param>
        /// <returns>The converted spell string.</returns>
        public static string ChineseToSpell(string str)
        {
            char[] chars = str.ToCharArray();

            var buffer = new StringBuilder();
            for (int i = 0; i < chars.Length; i++)
            {
                var chr = chars[i].ToString();
                if (StringToPinyinRegex.IsMatch(chr) == false)
                {
                    buffer.Append(chr);
                    continue;
                }

                int ascii = GetAsciiCode(chars[i]) - 65536;
                if (ascii > 0 && ascii < 160)
                {
                    buffer.Append(chr);
                }
                else
                {
                    if (ascii == -9254)
                        buffer.Append("Zhen"); // 修正“圳”字
                    else
                    {
                        for (int j = (Constants.PinyinAsciiValue.Length - 1); j >= 0; j--)
                        {
                            if (Constants.PinyinAsciiValue[j] <= ascii)
                            {
                                buffer.Append(Constants.PinyinSpellValue[j]);
                                break;
                            }
                        }
                    }
                }
            }

            return buffer.ToString();
        }

        /// <summary>
        /// Converts a byte array to hex string.
        /// </summary>
        /// <param name="bytes">Bytes to convert.</param>
        /// <returns>The converted hex string.</returns>
        public static string ByteArrayToHexString(byte[] bytes)
        {
            if (bytes == null || bytes.Length == 0)
                return string.Empty;

            int i = 0;
            char[] chars = new char[bytes.Length * 2];
            foreach (byte b in bytes)
            {
                string hex = Constants.HexStringTable[b];
                chars[i++] = hex[0];
                chars[i++] = hex[1];
            }

            return new string(chars);
        }

        /// <summary>
        /// Converts a hex string to byte array.
        /// </summary>
        /// <param name="hexString">Hex string to convert.</param>
        /// <returns>The converted bytes.</returns>
        public static byte[] HexStringToByteArray(string hexString)
        {
            byte[] bytes;
            int len = hexString.Length;

            if ((len % 2) != 0)
            {
                bytes = new byte[0];
            }
            else
            {
                int byteLen = len / 2;
                bytes = new byte[byteLen];
                for (int i = 0; i < byteLen; i++)
                {
                    bytes[i] = Convert.ToByte(hexString.Substring(i * 2, 2), 16);
                }
            }

            return bytes;
        }

        #endregion

        #region Methods

        #region DoRetry

        /// <summary>
        /// A retry mechanism, try to execute an <see cref="Action"/> using try-catch.
        /// </summary>
        /// <param name="retryTimes">The times for retry.</param>
        /// <param name="retryInterval">The retry interval in milliseconds.</param>
        /// <param name="tryAction">An <see cref="Action"/> delegate, encapsulates a method that takes no parameters and does not return a value.</param>
        /// <exception cref="T:ArgumentNullException">tryAction is null.</exception>
        public static void DoRetry(int retryTimes, int retryInterval, Action tryAction)
        {
            DoRetry(retryTimes, retryInterval, tryAction, null, null);
        }

        /// <summary>
        /// A retry mechanism, try to execute an <see cref="Action"/> using try-catch.
        /// </summary>
        /// <param name="retryTimes">The times for retry.</param>
        /// <param name="retryInterval">The retry interval in milliseconds.</param>
        /// <param name="tryAction">An <see cref="Action"/> delegate, encapsulates a method that takes no parameters and does not return a value.</param>
        /// <param name="catchAction">An <see cref="Action"/> delegate, encapsulates a method that takes <see cref="Exception"/> parameter and does not return a value.</param>
        /// <exception cref="T:ArgumentNullException">tryAction is null.</exception>
        public static void DoRetry(int retryTimes, int retryInterval, Action tryAction, Action<Exception> catchAction)
        {
            DoRetry(retryTimes, retryInterval, tryAction, catchAction, null);
        }

        /// <summary>
        /// A retry mechanism, try to execute an <see cref="Action"/> using try-catch.
        /// </summary>
        /// <param name="retryTimes">The times for retry.</param>
        /// <param name="retryInterval">The retry interval in milliseconds.</param>
        /// <param name="tryAction">An <see cref="Action"/> delegate, encapsulates a method that takes no parameters and does not return a value.</param>
        /// <param name="catchAction">An <see cref="Action"/> delegate, encapsulates a method that takes <see cref="Exception"/> parameter and does not return a value.</param>
        /// <param name="finallyAction">An <see cref="Action"/> delegate, encapsulates a method that takes no parameters and does not return a value.</param>
        /// <exception cref="T:ArgumentNullException">tryAction is null.</exception>
        public static void DoRetry(int retryTimes, int retryInterval, Action tryAction, Action<Exception> catchAction, Action<Exception> finallyAction)
        {
            if (tryAction == null)
                throw new ArgumentNullException("tryAction");

            for (int i = 1; i <= retryTimes; ++i)
            {
                try
                {
                    tryAction();
                    break;
                }
                catch (Exception ex)
                {
                    if (i == retryTimes)
                    {
                        if (finallyAction != null)
                            finallyAction(ex);
                    }
                    else
                    {
                        if (catchAction != null)
                            catchAction(ex);

                        if (retryInterval > 0)
                            Thread.Sleep(retryInterval);
                    }
                }
            }
        }

        #endregion

        #region DoTryCatch

        /// <summary>
        /// Try to execute an <see cref="Action"/> using try-catch.
        /// </summary>
        /// <param name="tryAction">An <see cref="Action"/> delegate, encapsulates a method that takes no parameters and does not return a value.</param>
        /// <exception cref="T:ArgumentNullException">tryAction is null.</exception>
        public static void DoTryCatch(Action tryAction)
        {
            DoTryCatch(tryAction, null, null);
        }

        /// <summary>
        /// Try to execute an <see cref="Action"/> using try-catch.
        /// </summary>
        /// <param name="tryAction">An <see cref="Action"/> delegate, encapsulates a method that takes no parameters and does not return a value.</param>
        /// <param name="catchAction">An <see cref="Action"/> delegate, encapsulates a method that takes <see cref="Exception"/> parameter and does not return a value.</param>
        /// <exception cref="T:ArgumentNullException">tryAction is null.</exception>
        public static void DoTryCatch(Action tryAction, Action<Exception> catchAction)
        {
            DoTryCatch(tryAction, catchAction, null);
        }

        /// <summary>
        /// Try to execute an <see cref="Action"/> using try-catch.
        /// </summary>
        /// <param name="tryAction">An <see cref="Action"/> delegate, encapsulates a method that takes no parameters and does not return a value.</param>
        /// <param name="catchAction">An <see cref="Action"/> delegate, encapsulates a method that takes <see cref="Exception"/> parameter and does not return a value.</param>
        /// <param name="finallyAction">An <see cref="Action"/> delegate, encapsulates a method that takes no parameters and does not return a value.</param>
        /// <exception cref="T:ArgumentNullException">tryAction is null.</exception>
        public static void DoTryCatch(Action tryAction, Action<Exception> catchAction, Action finallyAction)
        {
            if (tryAction == null)
                throw new ArgumentNullException("tryAction");

            try
            {
                tryAction();
            }
            catch (Exception ex)
            {
                if (catchAction != null) catchAction(ex);
            }
            finally
            {
                if (finallyAction != null) finallyAction();
            }
        }


        /// <summary>
        /// Try to execute an Func using try-catch.
        /// </summary>
        /// <param name="tryFunc">An Func delegate, encapsulates a method that takes no parameters and returns a value.</param>
        /// <exception cref="T:ArgumentNullException">tryFunc is null.</exception>
        /// <returns>If any error occurs and catchFunc is null, <c>default(TResult)</c> will be returned.</returns>
        public static TResult DoTryCatch<TResult>(Func<TResult> tryFunc)
        {
            return DoTryCatch(tryFunc, null, null);
        }

        /// <summary>
        /// Try to execute an Func using try-catch.
        /// </summary>
        /// <param name="tryFunc">An Func delegate, encapsulates a method that takes no parameters and returns a value.</param>
        /// <param name="catchFunc">An Func delegate, encapsulates a method that takes <see cref="Exception"/> parameter and returns a value.</param>
        /// <exception cref="T:ArgumentNullException">tryFunc is null.</exception>
        /// <returns>If any error occurs and catchFunc is null, <c>default(TResult)</c> will be returned.</returns>
        public static TResult DoTryCatch<TResult>(Func<TResult> tryFunc, Func<Exception, TResult> catchFunc)
        {
            return DoTryCatch(tryFunc, catchFunc, null);
        }

        /// <summary>
        /// Try to execute an Func using try-catch.
        /// </summary>
        /// <param name="tryFunc">An Func delegate, encapsulates a method that takes no parameters and returns a value.</param>
        /// <param name="catchFunc">An Func delegate, encapsulates a method that takes <see cref="Exception"/> parameter and returns a value.</param>
        /// <param name="finallyAction">An Func delegate, encapsulates a method that takes no parameters and does not return a value.</param>
        /// <exception cref="T:ArgumentNullException">tryFunc is null.</exception>
        /// <returns>If any error occurs and catchFunc is null, <c>default(TResult)</c> will be returned.</returns>
        public static TResult DoTryCatch<TResult>(Func<TResult> tryFunc, Func<Exception, TResult> catchFunc, Action finallyAction)
        {
            if (tryFunc == null)
                throw new ArgumentNullException("tryFunc");

            try
            {
                return tryFunc();
            }
            catch (Exception ex)
            {
                if (catchFunc != null)
                {
                    return catchFunc(ex);
                }

                return default(TResult);
            }
            finally
            {
                if (finallyAction != null) finallyAction();
            }
        }

        #endregion

        /// <summary>
        /// Gets a relative local path to the virtual path of web server.
        /// </summary>
        /// <param name="path">The path to get form.</param>
        /// <returns>The fully qualified path.</returns>
        /// <remarks>
        /// <para>
        /// Converts the path specified to a fully qualified path. 
        /// If the path is relative it is taken as relative from the application base directory.
        /// </para>
        /// <para>
        /// The path specified must be a local file path, a URI is not supported.
        /// </para>
        /// </remarks>
        public static string GetMapPath(string path)
        {
            HttpContext context = HttpContext.Current;
            if (context == null)
                return GetFullPath(path);
            else
                return context.Server.MapPath(path);
        }

        /// <summary>
        /// Gets a fully qualified local file path form a path.
        /// </summary>
        /// <param name="path">The path to get form.</param>
        /// <returns>The fully qualified path.</returns>
        /// <remarks>
        /// <para>
        /// Converts the path specified to a fully qualified path. 
        /// If the path is relative it is taken as relative from the application base directory.
        /// </para>
        /// <para>
        /// The path specified must be a local file path, a URI is not supported.
        /// </para>
        /// </remarks>
        public static string GetFullPath(string path)
        {
            if (path == null)
                throw new ArgumentNullException("path");

            path = path.Replace("/", "\\");
            if (path.StartsWith("\\"))
                path = path.TrimStart('\\');

            string baseDirectory = string.Empty;
            try
            {
                string appRoot = Utils.AppBaseDirectory;
                if (appRoot != null)
                {
                    // applicationBaseDirectory may be a URI not a local file path
                    Uri appRootUri = new Uri(appRoot);
                    if (appRootUri.IsFile)
                    {
                        baseDirectory = appRootUri.LocalPath;
                    }
                }
            }
            catch
            {
                // ignore uri exceptions
            }

            if (baseDirectory != null && baseDirectory.Length > 0)
            {
                // Note that Path.Combine will return the second path if it is rooted
                return Path.GetFullPath(Path.Combine(baseDirectory, path));
            }

            return Path.GetFullPath(path);
        }

        /// <summary>
        /// Gets the assembly location path for the specified assembly.
        /// </summary>
        /// <param name="assembly">The assembly to get the location for.</param>
        /// <returns>The location of the assembly.</returns>
        /// <remarks>
        /// This method does not guarantee to return the correct path
        /// to the assembly. If only tries to give an indication as to
        /// where the assembly was loaded from.
        /// </remarks>
        public static string GetAssemblyLocation(Assembly assembly)
        {
            if (assembly.GlobalAssemblyCache)
            {
                return "Global Assembly Cache";
            }
            else
            {
                try
                {
                    // This call requires FileIOPermission for access to the path
                    // if we don't have permission then we just ignore it and
                    // carry on.
                    return assembly.Location;
                }
                catch (SecurityException)
                {
                    return "Location Permission Denied";
                }
            }
        }

        /// <summary>
        /// Gets the short name of the <see cref="Assembly" />.
        /// </summary>
        /// <param name="myAssembly">The <see cref="Assembly" /> to get the name for.</param>
        /// <returns>The short name of the <see cref="Assembly" />.</returns>
        /// <remarks>
        /// <para>
        /// The short name of the assembly is the <see cref="Assembly.FullName" /> 
        /// without the version, culture, or public key. i.e. it is just the 
        /// assembly's file name without the extension.
        /// </para>
        /// <para>
        /// Use this rather than <c>Assembly.GetName().Name</c> because that
        /// is not available on the Compact Framework.
        /// </para>
        /// <para>
        /// Because of a FileIOPermission security demand we cannot do
        /// the obvious Assembly.GetName().Name. We are allowed to get
        /// the <see cref="Assembly.FullName" /> of the assembly so we 
        /// start from there and strip out just the assembly name.
        /// </para>
        /// </remarks>
        public static string GetAssemblyShortName(Assembly myAssembly)
        {
            string name = myAssembly.FullName;
            int offset = name.IndexOf(',');

            if (offset > 0)
                name = name.Substring(0, offset);

            return name.Trim();
        }

        /// <summary>
        /// Gets the file name portion of the <see cref="Assembly" />, including the extension.
        /// </summary>
        /// <param name="assembly">The <see cref="Assembly" /> to get the file name for.</param>
        /// <returns>The file name of the assembly.</returns>
        public static string GetAssemblyFileName(Assembly assembly)
        {
            return Path.GetFileName(assembly.Location);
        }

        /// <summary>
        /// Loads the type specified in the type string.
        /// </summary>
        /// <param name="typeName">The name of the type to load.</param>
        /// <param name="throwOnError">Flag set to <c>true</c> to throw an exception if the type cannot be loaded.</param>
        /// <param name="ignoreCase"><c>true</c> to ignore the case of the type name; otherwise, <c>false</c></param>
        /// <returns>The type loaded or <c>null</c> if it could not be loaded.</returns>		
        /// <remarks>
        /// <para>
        /// If the type name is fully qualified, i.e. if contains an assembly name in 
        /// the type name, the type will be loaded from the system using 
        /// <see cref="Type.GetType(string,bool)"/>.
        /// </para>
        /// <para>
        /// If the type name is not fully qualified it will be loaded from the
        /// assembly that is directly calling this method. If the type is not found 
        /// in the assembly then all the loaded assemblies will be searched for the type.
        /// </para>
        /// </remarks>
        public static Type GetTypeFromString(string typeName, bool throwOnError, bool ignoreCase)
        {
            return GetTypeFromString(Assembly.GetCallingAssembly(), typeName, throwOnError, ignoreCase);
        }

        /// <summary>
        /// Loads the type specified in the type string.
        /// </summary>
        /// <param name="relativeType">A sibling type to use to load the type.</param>
        /// <param name="typeName">The name of the type to load.</param>
        /// <param name="throwOnError">Flag set to <c>true</c> to throw an exception if the type cannot be loaded.</param>
        /// <param name="ignoreCase"><c>true</c> to ignore the case of the type name; otherwise, <c>false</c></param>
        /// <returns>The type loaded or <c>null</c> if it could not be loaded.</returns>
        /// <remarks>
        /// <para>
        /// If the type name is fully qualified, i.e. if contains an assembly name in 
        /// the type name, the type will be loaded from the system using 
        /// <see cref="Type.GetType(string,bool)"/>.
        /// </para>
        /// <para>
        /// If the type name is not fully qualified, it will be loaded from the assembly
        /// containing the specified relative type. If the type is not found in the assembly 
        /// then all the loaded assemblies will be searched for the type.
        /// </para>
        /// </remarks>
        public static Type GetTypeFromString(Type relativeType, string typeName, bool throwOnError, bool ignoreCase)
        {
            return GetTypeFromString(relativeType.Assembly, typeName, throwOnError, ignoreCase);
        }

        /// <summary>
        /// Loads the type specified in the type string.
        /// </summary>
        /// <param name="relativeAssembly">An assembly to load the type from.</param>
        /// <param name="typeName">The name of the type to load.</param>
        /// <param name="throwOnError">Flag set to <c>true</c> to throw an exception if the type cannot be loaded.</param>
        /// <param name="ignoreCase"><c>true</c> to ignore the case of the type name; otherwise, <c>false</c></param>
        /// <returns>The type loaded or <c>null</c> if it could not be loaded.</returns>
        /// <remarks>
        /// <para>
        /// If the type name is fully qualified, i.e. if contains an assembly name in 
        /// the type name, the type will be loaded from the system using <see cref="Type.GetType(string,bool)"/>.
        /// </para>
        /// <para>
        /// If the type name is not fully qualified it will be loaded from the specified
        /// assembly. If the type is not found in the assembly then all the loaded assemblies 
        /// will be searched for the type.
        /// </para>
        /// </remarks>
        public static Type GetTypeFromString(Assembly relativeAssembly, string typeName, bool throwOnError, bool ignoreCase)
        {
            // Check if the type name specifies the assembly name
            if (typeName.IndexOf(',') == -1)
            {
                // Attempt to lookup the type from the relativeAssembly
                Type type = relativeAssembly.GetType(typeName, false, ignoreCase);
                if (type != null)
                {
                    // Found type in relative assembly
                    return type;
                }

                Assembly[] loadedAssemblies = null;
                try
                {
                    loadedAssemblies = AppDomain.CurrentDomain.GetAssemblies();
                }
                catch (SecurityException)
                {
                    // Insufficient permissions to get the list of loaded assemblies
                }

                if (loadedAssemblies != null)
                {
                    // Search the loaded assemblies for the type
                    foreach (Assembly assembly in loadedAssemblies)
                    {
                        type = assembly.GetType(typeName, false, ignoreCase);
                        if (type != null)
                        {
                            // Found type in loaded assembly
                            return type;
                        }
                    }
                }

                // Didn't find the type
                if (throwOnError)
                {
                    throw new TypeLoadException("Could not load type [" + typeName + "]. Tried assembly [" + relativeAssembly.FullName + "] and all loaded assemblies.");
                }
                return null;
            }
            else
            {
                // Includes explicit assembly name
                return Type.GetType(typeName, throwOnError, ignoreCase);
            }
        }



        #region 字符串数组相关

        /// <summary>
        /// 分割字符串,不区分大小写。
        /// </summary>
        /// <param name="str">被拆分的字符串</param>
        /// <param name="separator">分隔符字符串</param>
        /// <returns>分割后字符串数组</returns>
        public static string[] SplitString(string str, string separator)
        {
            return SplitString(str, separator, true);
        }

        /// <summary>
        /// 分割字符串,指定是否不区分大小写。
        /// </summary>
        /// <param name="str">被拆分的字符串</param>
        /// <param name="separator">分隔符字符串</param>
        /// <param name="ignoreCase">是否不区分大小写， true为不区分，false为区分</param>
        /// <returns>分割后字符串数组</returns>
        public static string[] SplitString(string str, string separator, bool ignoreCase)
        {
            if (string.IsNullOrEmpty(str))
                return new string[0];

            if (str.IndexOf(separator) < 0)
                return new string[] { str };

            return Regex.Split(str, Regex.Escape(separator), ignoreCase ? RegexOptions.IgnoreCase : RegexOptions.None);
        }

        /// <summary>
        /// 分割字符串,只取前N项,不区分大小写。
        /// </summary>
        /// <param name="str">被拆分的字符串</param>
        /// <param name="separator">分隔符字符串</param>
        /// <param name="count">返回数组的前多少项</param>
        /// <returns>分割后字符串数组</returns>
        public static string[] SplitString(string str, string separator, int count)
        {
            return SplitString(str, separator, count, true);
        }

        /// <summary>
        /// 分割字符串,只取前N项,指定是否不区分大小写。
        /// </summary>
        /// <param name="str">被拆分的字符串</param>
        /// <param name="separator">分隔符字符串</param>
        /// <param name="count">返回数组的前多少项</param>
        /// <param name="ignoreCase">是否不区分大小写， true为不区分，false为区分</param>
        /// <returns>分割后字符串数组</returns>
        public static string[] SplitString(string str, string separator, int count, bool ignoreCase)
        {
            string[] strArray = SplitString(str, separator, ignoreCase);
            string[] retArray = new string[count < strArray.Length ? count : strArray.Length];

            for (int i = 0; i < retArray.Length; i++)
                retArray[i] = strArray[i];

            return retArray;
        }

        /// <summary>
        /// 分割字符串,删除空元素。
        /// </summary>
        /// <param name="str">被拆分的字符串</param>
        /// <param name="separator">分隔字符</param>
        /// <returns>分割后字符串数组</returns>
        public static string[] SplitString(string str, char separator)
        {
            return SplitString(str, separator, true);
        }

        /// <summary>
        /// 分割字符串,指定是否删除空元素
        /// </summary>
        /// <param name="str">被拆分的字符串</param>
        /// <param name="separator">分隔字符</param>
        /// <param name="removeEmpty">是否删除空元素, true为删除, false为不删除</param>
        /// <returns>分割后字符串数组</returns>
        public static string[] SplitString(string str, char separator, bool removeEmpty)
        {
            if (string.IsNullOrEmpty(str))
                return new string[0];

            if (str.IndexOf(separator) < 0)
                return new string[] { str };

            return str.Split(new char[] { separator }, int.MaxValue, removeEmpty ? StringSplitOptions.RemoveEmptyEntries : StringSplitOptions.None);
        }

        /// <summary>
        /// 分割字符串,只取前N项,删除空元素。
        /// </summary>
        /// <param name="str">被拆分的字符串</param>
        /// <param name="separator">分隔字符</param>
        /// <param name="count">返回数组的前多少项</param>
        /// <returns>分割后字符串数组</returns>
        public static string[] SplitString(string str, char separator, int count)
        {
            return SplitString(str, separator, count, true);
        }

        /// <summary>
        /// 分割字符串,只取前N项,指定是否不区分大小写。
        /// </summary>
        /// <param name="str">被拆分的字符串</param>
        /// <param name="separator">分隔字符</param>
        /// <param name="count">返回数组的前多少项</param>
        /// <param name="removeEmpty">是否删除空元素, true为删除, false为删除</param>
        /// <returns>分割后字符串数组</returns>
        public static string[] SplitString(string str, char separator, int count, bool removeEmpty)
        {
            string[] strArray = SplitString(str, separator, removeEmpty);
            string[] retArray = new string[strArray.Length > count ? count : strArray.Length];

            for (int i = 0; i < retArray.Length; i++)
                retArray[i] = strArray[i];

            return retArray;
        }


        /// <summary>
        /// 以分隔符串连接字符串数组的各项。
        /// </summary>
        /// <param name="strArray">要处理的字符串</param>
        /// <param name="separator">分隔字符串</param>
        /// <returns></returns>
        public static string JionStringArray(string[] strArray, string separator)
        {
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < strArray.Length; i++)
            {
                sb.Append(strArray[i]);
                if (i < strArray.Length - 1)
                    sb.Append(separator);
            }

            return sb.ToString();
        }


        /// <summary>
        /// 判断指定字符串在指定字符串数组中的位置,不区分大小写。
        /// </summary>
        /// <param name="strSearch">字符串</param>
        /// <param name="stringArray">字符串数组</param>
        /// <returns>字符串在指定字符串数组中的位置, 如不存在则返回-1</returns>		
        public static int InStringArrayIndex(string strSearch, string[] stringArray)
        {
            return InStringArrayIndex(strSearch, stringArray, true);
        }

        /// <summary>
        /// 判断指定字符串在指定字符串数组中的位置。
        /// </summary>
        /// <param name="strSearch">字符串</param>
        /// <param name="stringArray">字符串数组</param>
        /// <param name="ignoreCase">是否不区分大小写， true为不区分，false为区分</param>
        /// <returns>字符串在指定字符串数组中的位置, 如不存在则返回-1</returns>
        public static int InStringArrayIndex(string strSearch, string[] stringArray, bool ignoreCase)
        {
            if (ignoreCase)
            {
                for (int i = 0; i < stringArray.Length; i++)
                {
                    if (strSearch.ToLower() == stringArray[i].ToLower())
                        return i;
                }
            }
            else
            {
                for (int i = 0; i < stringArray.Length; i++)
                {
                    if (strSearch == stringArray[i])
                        return i;
                }
            }
            return -1;
        }

        /// <summary>
        /// 判断指定字符串是否属于指定字符串数组中的一个元素,区分大小写。
        /// </summary>
        /// <param name="str">字符串</param>
        /// <param name="arrString">字符串数组</param>
        /// <returns>判断结果</returns>
        public static bool InStringArray(string str, string[] arrString)
        {
            return InStringArray(str, arrString, false);
        }

        /// <summary>
        /// 判断指定字符串是否属于指定字符串数组中的一个元素
        /// </summary>
        /// <param name="strSearch">字符串</param>
        /// <param name="stringArray">字符串数组</param>
        /// <param name="ignoreCase">是否不区分大小写， true为不区分，false为区分</param>
        /// <returns>判断结果</returns>
        public static bool InStringArray(string strSearch, string[] stringArray, bool ignoreCase)
        {
            return InStringArrayIndex(strSearch, stringArray, ignoreCase) > -1;
        }

        /// <summary>
        /// 判断指定字符串是否属于指定字符串数组中的一个元素，区分大小写。
        /// </summary>
        /// <param name="str">字符串</param>
        /// <param name="arrString">被拆分的字符串</param>
        /// <param name="separator">分割字符串</param>
        /// <returns>判断结果</returns>
        public static bool InStringArray(string str, string arrString, string separator)
        {
            return InStringArray(str, SplitString(arrString, separator), false);
        }

        /// <summary>
        /// 判断指定字符串是否属于指定字符串数组中的一个元素。
        /// </summary>
        /// <param name="str">要查找的字符串</param>
        /// <param name="arrString">被拆分的字符串</param>
        /// <param name="separator">分割字符串</param>
        /// <param name="ignoreCase">是否不区分大小写， true为不区分，false为区分</param>
        /// <returns>判断结果</returns>
        public static bool InStringArray(string str, string arrString, string separator, bool ignoreCase)
        {
            return InStringArray(str, SplitString(arrString, separator), ignoreCase);
        }

        #endregion

        #region AppendToArray

        /// <summary>
        /// Appends new items to an array.
        /// </summary>
        /// <typeparam name="T">The type of the array.</typeparam>
        /// <param name="array">The array being appended to.</param>
        /// <param name="newItems">The new items to append to the array being appended to.</param>
        public static void AppendToArray<T>(ref T[] array, params T[] newItems)
        {
            if (newItems == null || newItems.Length == 0)
                return;

            Array.Resize<T>(ref array, array.Length + newItems.Length);
            Array.Copy(newItems, 0, array, array.Length - newItems.Length, newItems.Length);
        }

        #endregion AppendToArray

        #region String Related

        /// <summary>
        /// Gets a new Guid string using Guid.NewGuid().ToString("N").
        /// </summary>
        /// <returns>The new Guid string.</returns>
        public static string NewGuidString()
        {
            return Guid.NewGuid().ToString("N");
        }

        /// <summary>
        /// Gets reverse string of a specified string.
        /// </summary>
        /// <param name="str">The string to reverse.</param>
        /// <returns>The reversed string.</returns>
        public static string ReverseString(string str)
        {
            if (string.IsNullOrEmpty(str))
                return string.Empty;

            int length = str.Length;

            if (length < 2)
                return str;

            char[] chars = str.ToCharArray();

            if (length >= 15)
                Array.Reverse(chars);
            else
            {
                char temp;
                int index = 0;
                int middle = (length - length % 2) / 2;

                while (--middle >= 0)
                {
                    temp = chars[index];
                    chars[index] = str[--length];
                    chars[length] = str[index++];
                }
            }

            return new string(chars);
        }

        /// <summary>
        /// Gets a sub string from a source string.
        /// </summary>
        /// <param name="str">The string to get sub string from.</param>
        /// <param name="length">The length of sub string.</param>
        /// <returns>The final sub string.</returns>
        public static string GetSubString(string str, int length)
        {
            return GetSubString(str, length, string.Empty);
        }

        /// <summary>
        /// Gets a sub string from a source string.
        /// </summary>
        /// <param name="str">The string to get sub string from.</param>
        /// <param name="length">The length of sub string.</param>
        /// <param name="tail">
        /// The tail of sub string if the specified <paramref name="length"/> 
        /// exceeds the length of source string.
        /// </param>
        /// <returns>The final sub string.</returns>
        public static string GetSubString(string str, int length, string tail)
        {
            string ret = str;

            //// 当是日文或韩文时
            //// 中文: \u4e00 - \u9fa5, 日文: \u0800 - \u4e00, 韩文: \xAC00-\xD7A3
            //if (Regex.IsMatch(ret, "[\u0800-\u4e00]+") 
            //    || Regex.IsMatch(ret, "[\xAC00-\xD7A3]+"))
            //{
            //    if (length >= ret.Length)
            //        return ret;
            //    else
            //        return length > 0 ? ret.Substring(0, length) : ret;
            //}

            //判断字符串长度是否大于截断长度
            if (Utils.GetBytesLength(ret) > length)
            {
                int i = 0, j = 0;
                //为汉字或全角符号长度加2否则加1
                foreach (char c in ret.ToCharArray())
                {
                    i = ((int)c > 127) ? i + 2 : i + 1;

                    if (i > length)
                    {
                        ret = ret.Substring(0, j) + tail;
                        break;
                    }
                    j++;
                }
            }
            return ret;
        }


        #region  xml字符转义
        /// <summary>
        /// 
        /// </summary>
        /// <param name="s"></param>
        /// <returns></returns>
        public static string EscapeXml(this string s)
        {
            string str = s;
            if (!string.IsNullOrEmpty(str))
            {
                str = str.Replace("&", "&amp;").Replace("<", "&lt;").Replace(">", "&gt;").Replace("\"", "&quot;").Replace("'", "&apos;");
            }
            return str;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="s"></param>
        /// <returns></returns>
        public static string UnescapeXml(this string s)
        {
            string str = s;
            if (!string.IsNullOrEmpty(str))
            {
                str = str.Replace("&apos;", "'").Replace("&quot;", "\"").Replace("&gt;", ">").Replace("&lt;", "<").Replace("&amp;", "&");
            }
            return str;
        }

        #endregion xml字符转义

        #region WebService 数据传输时处理特别字符用到

        /// <summary>
        /// <![CDATA[
        /// 把一个字符串中的 低序位 ASCII 字符 去掉。
        /// 转换  ASCII  0 - 8  -> &#x0 - &#x8
        /// 转换  ASCII 11 - 12 -> &#xB - &#xC
        /// 转换  ASCII 14 - 31 -> &#xE - &#x1F
        /// ]]>
        /// </summary>
        /// <param name="str">要处理的字符串</param>
        public static string TrimLowOrderASCIICharacters(string str)
        {
            StringBuilder info = new StringBuilder();
            foreach (char cc in str)
            {
                int ss = (int)cc;
                if (((ss >= 0) && (ss <= 8)) || ((ss >= 11) && (ss <= 12)) || ((ss >= 14) && (ss <= 32)))
                    info.AppendFormat(" ", ss);//&#x{0:X};
                else info.Append(cc);
            }
            return info.ToString();
        }

        /// <summary>
        /// <![CDATA[
        /// 把一个字符串中的 低序位 ASCII 字符 替换成 &#x  字符。
        /// 转换  ASCII  0 - 8  -> &#x0 - &#x8
        /// 转换  ASCII 11 - 12 -> &#xB - &#xC
        /// 转换  ASCII 14 - 31 -> &#xE - &#x1F
        /// ]]>
        /// </summary>
        /// <param name="str">要处理的字符串</param>
        /// <returns></returns>
        public static string ReplaceLowOrderASCIICharacters(string str)
        {
            StringBuilder sb = new StringBuilder();
            foreach (char c in str)
            {
                int s = (int)c;
                if (((s >= 0) && (s <= 8)) || ((s >= 11) && (s <= 12)) || ((s >= 14) && (s <= 32)))
                    sb.AppendFormat("&#x{0:X};", s);
                else
                    sb.Append(c);
            }

            return sb.ToString();
        }

        /// <summary>
        /// <![CDATA[
        /// 把一个字符串中的下列字符替换成 低序位 ASCII 字符。
        /// 转换  &#x0 - &#x8  -> ASCII  0 - 8
        /// 转换  &#xB - &#xC  -> ASCII 11 - 12
        /// 转换  &#xE - &#x1F -> ASCII 14 - 31
        /// ]]>
        /// </summary>
        /// <param name="str">要处理的字符串</param>
        /// <returns></returns>
        public static string GetLowOrderASCIICharacters(string str)
        {
            if (string.IsNullOrEmpty(str))
                return string.Empty;

            int pos, startIndex = 0, len = str.Length;
            if (len <= 4) return str;

            StringBuilder sb = new StringBuilder();
            while ((pos = str.IndexOf("&#x", startIndex)) >= 0)
            {
                bool needReplace = false;
                string rOldV = string.Empty, rNewV = string.Empty;
                int le = (len - pos < 6) ? len - pos : 6;
                int p = str.IndexOf(";", pos, le);
                if (p >= 0)
                {
                    rOldV = str.Substring(pos, p - pos + 1);
                    // 计算 对应的低位字符
                    short ss;
                    if (short.TryParse(rOldV.Substring(3, p - pos - 3), System.Globalization.NumberStyles.AllowHexSpecifier, null, out ss))
                    {
                        if (((ss >= 0) && (ss <= 8)) || ((ss >= 11) && (ss <= 12)) || ((ss >= 14) && (ss <= 32)))
                        {
                            needReplace = true;
                            rNewV = Convert.ToChar(ss).ToString();
                        }
                    }
                    pos = p + 1;
                }
                else
                    pos += le;

                string part = str.Substring(startIndex, pos - startIndex);

                if (needReplace)
                    sb.Append(part.Replace(rOldV, rNewV));
                else
                    sb.Append(part);
                startIndex = pos;
            }
            sb.Append(str.Substring(startIndex));

            return sb.ToString();
        }

        #endregion

        #endregion


        #region GetASCIICode/GetFirstLetterSymbolForChinese

        /// <summary>
        /// Gets the ASC code of a char.
        /// </summary>
        /// <param name="c">a char.</param>
        /// <returns>The ASC code of the char.</returns>
        internal static int GetAsciiCode(char c)
        {
            return GetAsciiCode(c.ToString());
        }

        /// <summary>
        /// Gets the ASC code of a string.
        /// </summary>
        /// <param name="str">a string.</param>
        /// <returns>The ASC code of the string.</returns>
        internal static int GetAsciiCode(string str)
        {
            int asc = 0;
            byte[] bytes = Encoding.Default.GetBytes(str);

            if (bytes.Length == 1)
                return (int)bytes[0];

            for (int i = 0; i < bytes.Length; i += 2)
            {
                asc = (int)bytes[i] * 256 + (int)bytes[i + 1];
            }

            return asc;
            //return asc - 65536;
        }

        /// <summary>
        /// Gets the first letter symbol of a string for chinese spell, e.g. 
        /// "中"-"Z", "1"-"1", "a"-"A", "ん"-"ん".
        /// </summary>
        /// <param name="str">A string to get symbol from.</param>
        /// <returns>The letter symbol.</returns>
        public static string GetFirstLetterOfSpell(string str)
        {
            return ChineseToSpell(str[0].ToString())[0].ToString().ToUpper();
        }

        /// <summary>
        /// Gets the first letter symbol of a string for chinese spell for singer, 
        /// e.g. "中"-"Z", "1"-"1", "a"-"A", "ん"-"0-9".
        /// </summary>
        /// <param name="str">A string to get symbol from.</param>
        /// <returns>The letter symbol.</returns>
        public static string GetFirstLetterOfSpellForSinger(string str)
        {
            var ch = char.ToUpper(ChineseToSpell(str[0].ToString())[0]);

            return (ch >= 'A' && ch <= 'Z') ? ch.ToString() : "0-9";
        }

        #endregion


        #region File

        /// <summary>
        /// Determines whether the specified file exists.
        /// </summary>
        /// <param name="path">The file to check.</param>
        /// <returns>
        /// true if the caller has the required permissions and path contains the name 
        /// of an existing file; otherwise, false. This method also returns false if 
        /// path is null, an invalid path, or a zero-length string. If the caller does 
        /// not have sufficient permissions to read the specified file, no exception 
        /// is thrown and the method returns false regardless of the existence of path.
        /// </returns>
        public static bool FileExists(string path)
        {
            return File.Exists(path);
        }

        /// <summary>
        /// Deletes the specified file. An exception is not thrown if the specified file 
        /// does not exist.
        /// </summary>
        /// <param name="path">The name of the file to be deleted.</param>
        public static void DeleteFile(string path)
        {
            FileInfo file = new FileInfo(path);
            if ((file.Attributes & FileAttributes.ReadOnly) == FileAttributes.ReadOnly)
            {
                // add attributes
                //file.Attributes |= FileAttributes.ReadOnly;
                // remove attributes
                file.Attributes &= ~FileAttributes.ReadOnly;
            }

            file.Delete();
        }

        /// <summary>
        /// Moves a specified file to a new location, providing the option to specify 
        /// a new file name.
        /// </summary>
        /// <param name="sourceFileName">The name of the file to move.</param>
        /// <param name="destFileName">The new path for the file. If destFileName exists, it will be deleted before moving.</param>
        public static void MoveFile(string sourceFileName, string destFileName)
        {
            if (File.Exists(destFileName))
                DeleteFile(destFileName);
            else
            {
                string dir = Path.GetDirectoryName(destFileName);
                if (!Directory.Exists(dir))
                    Directory.CreateDirectory(dir);
            }

            File.Move(sourceFileName, destFileName);
        }

        /// <summary>
        /// Copies an existing file to a new file. Overwriting a file of the same name 
        /// is not allowed.
        /// </summary>
        /// <param name="sourceFileName">The file to copy.</param>
        /// <param name="destFileName">The name of the destination file. This cannot be a directory or an existing file.</param>
        public static void CopyFile(string sourceFileName, string destFileName)
        {
            CopyFile(sourceFileName, destFileName, false);
        }

        /// <summary>
        /// Copies an existing file to a new file.
        /// </summary>
        /// <param name="sourceFileName">The file to copy.</param>
        /// <param name="destFileName">The name of the destination file. This cannot be a directory.</param>
        /// <param name="overwrite">True if the destination file can be overwritten; otherwise, false.</param>
        public static void CopyFile(string sourceFileName, string destFileName, bool overwrite)
        {
            string dir = Path.GetDirectoryName(destFileName);
            if (!Directory.Exists(dir))
                Directory.CreateDirectory(dir);

            File.Copy(sourceFileName, destFileName, overwrite);
        }


        /// <summary>
        /// Gets the hash hexadecimal string(binary fingerprint) of a file.
        /// </summary>
        /// <param name="path">The file to get hash string from.</param>
        /// <returns>The hash hexadecimal string of the file.</returns>
        public static string GetFileMd5HashString(string path)
        {
            if (!File.Exists(path))
                throw new FileNotFoundException(string.Format("The file({0}) doesn't exists.", path));

            string hashString = string.Empty;

            using (FileStream fs = new FileStream(path, FileMode.Open))
            {
                hashString = GetFileMd5HashString(fs);
                fs.Close();
            }

            return hashString;
        }

        /// <summary>
        /// Gets the md5 hash hexadecimal string(binary fingerprint) of a file stream.
        /// </summary>
        /// <param name="stream">The stream of a file.</param>
        /// <returns>The hash hexadecimal string of the file stream.</returns>
        public static string GetFileMd5HashString(FileStream stream)
        {
            return CryptoService.MD5.EncryptToHexString(stream).ToUpper();
        }

        /// <summary>
        /// Gets a bool indicates whether the specified files are the same by checking md5 hash string.
        /// </summary>
        /// <param name="fileName1">The first file to check.</param>
        /// <param name="fileName2">The second file to check.</param>
        /// <param name="otherFileNames">The other files to check.</param>
        /// <returns>True if the specified files are the same; otherwise false.</returns>
        public static bool IsEqualFiles(string fileName1, string fileName2, params string[] otherFileNames)
        {
            string hash = GetFileMd5HashString(fileName1);

            if (hash != GetFileMd5HashString(fileName2))
                return false;

            if (otherFileNames != null && otherFileNames.Length > 0)
            {
                foreach (var f in otherFileNames)
                {
                    if (hash != GetFileMd5HashString(f))
                        return false;
                }
            }

            return true;
        }

        #endregion

        #region Directory

        /// <summary>
        /// Determines whether the given path refers to an existing directory on disk.
        /// </summary>
        /// <param name="path">The path to test.</param>
        /// <returns>True if path refers to an existing directory; otherwise, false.</returns>
        public static bool DirectoryExists(string path)
        {
            return Directory.Exists(path);
        }

        /// <summary>
        /// Creates all directories and subdirectories as specified by path.
        /// </summary>
        /// <param name="path">The directory path to create.</param>
        /// <returns>A <see cref="System.IO.DirectoryInfo"/> as specified by path.</returns>
        public static DirectoryInfo CreateDirectory(string path)
        {
            return Directory.CreateDirectory(path);
        }

        /// <summary>
        /// Ensures that the specified directory exists.
        /// </summary>
        /// <param name="path">The directory path.</param>
        /// <returns>A <see cref="System.IO.DirectoryInfo"/> as specified by path.</returns>
        public static DirectoryInfo EnsureDirectory(string path)
        {
            DirectoryInfo dir = null;

            if (Directory.Exists(path))
                dir = new DirectoryInfo(path);
            else
                dir = Directory.CreateDirectory(path);

            return dir;
        }

        /// <summary>
        /// Ensures that the directory of specified file exists.
        /// </summary>
        /// <param name="path">The file path.</param>
        /// <returns>A <see cref="System.IO.DirectoryInfo"/> as specified by path.</returns>
        public static DirectoryInfo EnsureDirectoryOfFile(string path)
        {
            return EnsureDirectory(Path.GetDirectoryName(path));
        }

        /// <summary>
        /// Deletes an empty directory from a specified path.
        /// </summary>
        /// <param name="path">The name of the empty directory to remove. This directory must be writable or empty.</param>
        public static void DeleteDirectory(string path)
        {
            DeleteDirectory(path, false);
        }

        /// <summary>
        /// Deletes the specified directory and, if indicated, any subdirectories in the directory.
        /// </summary>
        /// <param name="path">The name of the directory to remove.</param>
        /// <param name="recursive">true to remove directories, subdirectories, and files in path; otherwise, false.</param>
        public static void DeleteDirectory(string path, bool recursive)
        {
            DirectoryInfo dir = new DirectoryInfo(path);
            if ((dir.Attributes & FileAttributes.ReadOnly) == FileAttributes.ReadOnly)
            {
                // add attributes
                //dir.Attributes |= FileAttributes.ReadOnly;
                // remove attributes
                dir.Attributes &= ~FileAttributes.ReadOnly;
            }

            dir.Delete(recursive);
        }

        /// <summary>
        /// Moves a file or a directory and its contents to a new location.
        /// </summary>
        /// <param name="sourceDirName">The path of the file or directory to move.</param>
        /// <param name="destDirName">The path to the new location for sourceDirName. If sourceDirName is a file, 
        /// then destDirName must also be a file name.</param>
        public static void MoveDirectory(string sourceDirName, string destDirName)
        {
            if (File.Exists(destDirName))
                File.Delete(destDirName);
            if (Directory.Exists(destDirName))
                Directory.Delete(destDirName, true);

            string destDir = Path.GetDirectoryName(destDirName);
            if (!Directory.Exists(destDir))
                Directory.CreateDirectory(destDir);

            Directory.Move(sourceDirName, destDirName);
        }

        /// <summary>
        /// Copies an existing directory to a new directory. Overwriting a file of the same name 
        /// is allowed.
        /// </summary>
        /// <param name="sourceDirName">The directory to copy.</param>
        /// <param name="destDirName">The name of the destination directory.</param>
        public static void CopyDirectory(string sourceDirName, string destDirName)
        {
            CopyDirectory(sourceDirName, destDirName, false);
        }

        /// <summary>
        /// Copies an existing directory to a new directory.
        /// </summary>
        /// <param name="sourceDirName">The directory to copy.</param>
        /// <param name="destDirName">The name of the destination directory.</param>
        /// <param name="overwrite">True if the file in destination directory can be overwritten; otherwise, false.</param>
        public static void CopyDirectory(string sourceDirName, string destDirName, bool overwrite)
        {
            if (!Directory.Exists(destDirName))
                Directory.CreateDirectory(destDirName);

            DirectoryInfo source = new DirectoryInfo(sourceDirName);
            if (source.Exists)
            {
                foreach (FileSystemInfo f in source.GetFileSystemInfos())
                {
                    if (f is FileInfo)
                        Utils.CopyFile(f.FullName, Path.Combine(destDirName, f.Name), overwrite);
                    else if (f is DirectoryInfo)
                        CopyDirectory(f.FullName, Path.Combine(destDirName, f.Name), overwrite);
                }
            }
        }

        /// <summary>
        /// Combines an existing directory to another existing directory.
        /// </summary>
        /// <param name="sourceDirName">The directory to combine.</param>
        /// <param name="destDirName">The name of the destination directory.</param>
        public static void CombineDirectory(string sourceDirName, string destDirName)
        {
            if (!Directory.Exists(destDirName))
                Directory.CreateDirectory(destDirName);

            DirectoryInfo source = new DirectoryInfo(sourceDirName);
            if (source.Exists)
            {
                foreach (FileSystemInfo f in source.GetFileSystemInfos())
                {
                    if (f is FileInfo)
                        Utils.MoveFile(f.FullName, Path.Combine(destDirName, f.Name));
                    else if (f is DirectoryInfo)
                        CombineDirectory(Path.Combine(sourceDirName, f.Name), Path.Combine(destDirName, f.Name));
                }
            }
        }

        /// <summary>
        /// Gets the size, in bytes, of the specified directory with subdirectories.
        /// </summary>
        /// <param name="dirName">The path of directory to get size from.</param>
        /// <returns>The size of the directory in bytes.</returns>
        public static long GetDirectorySize(string dirName)
        {
            return GetDirectorySize(dirName, true);
        }

        /// <summary>
        /// Gets the size, in bytes, of the specified directory.
        /// </summary>
        /// <param name="dirName">The path of directory to get size from.</param>
        /// <param name="recursive">True to calculate size of directories, subdirectories, and files in path; otherwise, false.</param>
        /// <returns>The size of the directory in bytes.</returns>
        public static long GetDirectorySize(string dirName, bool recursive)
        {
            long size = 0;
            DirectoryInfo dir = new DirectoryInfo(dirName);

            if (dir.Exists)
            {
                foreach (FileSystemInfo f in dir.GetFileSystemInfos())
                {
                    if (f is FileInfo)
                        size += ((FileInfo)f).Length;
                    else if (recursive && (f is DirectoryInfo))
                        size += GetDirectorySize(f.FullName, recursive);
                }
            }

            return size;
        }

        #endregion

        #region Other

        /// <summary>
        /// Gets the content type string by a file name.
        /// </summary>
        /// <param name="fileName">The file name to get content type from.</param>
        /// <returns>The content type found.</returns>
        public static string GetContentType(string fileName)
        {
            string ext = Path.GetExtension(fileName).Trim().ToLower();
            if (string.IsNullOrEmpty(ext)
                || Constants.FileContentTypes.ContainsKey(ext) == false)
            {
                RegistryKey rk = Registry.ClassesRoot.OpenSubKey(ext);
                if (rk != null)
                {
                    object mimeType = rk.GetValue("Content Type");
                    if (mimeType != null)
                        return mimeType.ToString();
                }

                return Constants.FileContentTypes[".*"];
            }
            else
                return Constants.FileContentTypes[ext];
        }

        /// <summary>
        /// Returns the Encoding of a text file. Returns Encoding.Default if no Unicode BOM (byte order mark) is found.
        /// </summary>
        /// <param name="fileName">The file name.</param>
        /// <returns>The Encoding of the text file, returns Encoding.Default if no Unicode BOM (byte order mark) is found.</returns>
        public static Encoding GetTextFileEncoding(string fileName)
        {
            Encoding result = null;
            FileInfo file = new FileInfo(fileName);
            Encoding[] encodings = { Encoding.BigEndianUnicode, Encoding.Unicode, Encoding.UTF8 };

            using (var fs = file.OpenRead())
            {
                for (int i = 0; result == null && i < encodings.Length; i++)
                {
                    fs.Position = 0;
                    bool preamblesAreEqual = true;
                    byte[] preamble = encodings[i].GetPreamble();

                    for (int j = 0; preamblesAreEqual && j < preamble.Length; j++)
                    {
                        preamblesAreEqual = preamble[j] == fs.ReadByte();
                    }

                    if (preamblesAreEqual)
                        result = encodings[i];
                }
                fs.Close();
            }

            if (result == null)
                result = Encoding.Default;

            return result;
        }

        #region GetFileSizeString/GetFileSizeFromString

        /// <summary>
        /// Gets string expression of file size in format: 
        /// number + Bytes/KB/MB/GB/TB/EB.
        /// </summary>
        /// <param name="bytes">The bytes count of file size.</param>
        /// <returns>The string expression of file size.</returns>
        public static string GetFileSizeString(int bytes)
        {
            return GetFileSizeString(bytes, 2);
        }

        /// <summary>
        /// Gets string expression of file size in format: 
        /// number + Bytes/KB/MB/GB/TB/EB.
        /// </summary>
        /// <param name="bytes">The bytes count of file size.</param>
        /// <returns>The string expression of file size.</returns>
        public static string GetFileSizeString(long bytes)
        {
            return GetFileSizeString(bytes, 2);
        }

        /// <summary>
        /// Gets string expression of file size in format: 
        /// number + Bytes/KB/MB/GB/TB/EB.
        /// </summary>
        /// <param name="bytes">The bytes count of file size.</param>
        /// <param name="round">The decimal fraction to reserve.</param>
        /// <returns>The string expression of file size.</returns>
        public static string GetFileSizeString(int bytes, int round)
        {
            return GetFileSizeString((long)bytes, round);
        }

        /// <summary>
        /// Gets string expression of file size in format: 
        /// number + Bytes/KB/MB/GB/TB/EB.
        /// </summary>
        /// <param name="bytes">The bytes count of file size.</param>
        /// <param name="round">The decimal fraction to reserve.</param>
        /// <returns>The string expression of file size.</returns>
        public static string GetFileSizeString(long bytes, int round)
        {
            int rank = 0;
            double size = (double)bytes;
            while (size / 1024d > 1)
            {
                rank++;
                size = size / 1024d;
            }
            size = (double)System.Math.Round(size, round);

            switch (rank)
            {
                case 0: return size.ToString(CultureInfo.InvariantCulture) + "Bytes";
                case 1: return size.ToString(CultureInfo.InvariantCulture) + "KB";
                case 2: return size.ToString(CultureInfo.InvariantCulture) + "MB";
                case 3: return size.ToString(CultureInfo.InvariantCulture) + "GB";
                case 4: return size.ToString(CultureInfo.InvariantCulture) + "TB";
                case 5: return size.ToString(CultureInfo.InvariantCulture) + "EB";
                default: return "0Bytes";
            }
        }

        /// <summary>
        /// Gets the bytes count of a file size string generated by <see cref="M:Utils.GetFileSizeString()"/>.
        /// </summary>
        /// <param name="sizeString">The file size in format: number + Bytes/KB/MB/GB/TB/EB.</param>
        /// <returns>The bytes count of the specified file size string.</returns>
        public static long GetFileSizeFromString(string sizeString)
        {
            double fileSzie = 0;
            string sizeUnit = string.Empty;
            for (int i = 0; i < sizeString.Length; i++)
            {
                if (char.IsLetter(sizeString[i]))
                {
                    fileSzie = double.Parse(sizeString.Substring(0, i));
                    sizeUnit = sizeString.Substring(i).Trim().ToUpper();
                    break;
                }
            }

            if (fileSzie == 0)
                return 0;

            switch (sizeUnit)
            {
                case "BYTES": break;
                case "KB": fileSzie = fileSzie * 1024; break;
                case "MB": fileSzie = fileSzie * 1024 * 1024; break;
                case "GB": fileSzie = fileSzie * 1024 * 1024 * 1024; break;
                case "TB": fileSzie = fileSzie * 1024 * 1024 * 1024 * 1024; break;
                case "EB": fileSzie = fileSzie * 1024 * 1024 * 1024 * 1024 * 1024; break;
                default: fileSzie = 0f; break;
            }

            return Convert.ToInt64(fileSzie, CultureInfo.InvariantCulture);
        }

        #endregion

        #endregion


        #region  CollectionOperate

        /// <summary>
        /// Converts a KeyValuePair&lt;string, string&gt; collection to url 
        /// query string (e.g. q1=v1&amp;q2=v2&amp;qn=vn).
        /// </summary>
        /// <param name="keyValuePairs">A KeyValuePair&lt;string, string&gt; collection.</param>
        /// <returns>The converted string.</returns>
        public static string ToQueryString(this IEnumerable<KeyValuePair<string, string>> keyValuePairs)
        {
            keyValuePairs.ThrowsIfNull("keyValuePairs");

            var first = true;
            var buffer = new StringBuilder();
            foreach (var pair in keyValuePairs)
            {
                if (first)
                    buffer.AppendFormat("{0}={1}", pair.Key, pair.Value);
                else
                    buffer.AppendFormat("&{0}={1}", pair.Key, pair.Value);
            }

            return buffer.ToString();
        }

        /// <summary>
        /// Combines the items in an enumerable collection with comma(,).
        /// </summary>
        /// <typeparam name="T">The type of items in the collection.</typeparam>
        /// <param name="collection">An enumerable collection.</param>
        /// <returns>The combined string.</returns>
        public static string ToCommaString<T>(IEnumerable<T> collection)
        {
            return CombineCollection<T>(collection, ",", null, null);
        }

        /// <summary>
        /// Combines the items in an enumerable collection with a separator.
        /// </summary>
        /// <typeparam name="T">The type of items in the collection.</typeparam>
        /// <param name="collection">An enumerable collection.</param>
        /// <param name="separator">The separator to combine the collection items with.</param>
        /// <returns>The combined string.</returns>
        public static string CombineCollection<T>(IEnumerable<T> collection, string separator)
        {
            return CombineCollection<T>(collection, separator, null, null);
        }

        /// <summary>
        /// Combines the items in an enumerable collection with a separator, each item 
        /// will be fixed with the specified prefix and suffix.
        /// </summary>
        /// <typeparam name="T">The type of items in the collection.</typeparam>
        /// <param name="collection">An enumerable collection.</param>
        /// <param name="separator">The separator to combine the collection items with.</param>
        /// <param name="prefix">The prefix to fix the collection items with.</param>
        /// <param name="suffix">The suffix to fix the collection items with.</param>
        /// <returns>The combined string.</returns>
        public static string CombineCollection<T>(IEnumerable<T> collection, string separator, string prefix, string suffix)
        {
            collection.ThrowsIfNull("collection");

            var buffer = new StringBuilder();
            foreach (var t in collection)
            {
                T curr = t;

                if (curr == null)
                    continue;

                var val = curr.ToString();

                if (val.Length == 0)
                    continue;

                if (buffer.Length > 0)
                    buffer.Append(separator);

                if (prefix != null) buffer.Append(prefix);
                buffer.Append(val);
                if (suffix != null) buffer.Append(suffix);
            }
            return buffer.ToString();
        }

        #endregion
        #endregion Public Static Methods

        #region 正则表达式验证 Fields

        private static readonly Encoding BG2312Encoding = Encoding.GetEncoding("gb2312");

        private static readonly Regex UrlRegex = new Regex(@"^(http|https)\://([a-zA-Z0-9\.\-]+(\:[a-zA-Z0-9\.&%\$\-]+)*@)*((25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9])\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[0-9])|localhost|([a-zA-Z0-9\-]+\.)*[a-zA-Z0-9\-]+\.(com|edu|gov|int|mil|net|org|biz|arpa|info|name|pro|aero|coop|museum|[a-zA-Z]{1,10}))(\:[0-9]+)*(/($|[a-zA-Z0-9\.\,\?\'\\\+&%\$#\=~_\-]+))*$", RegexOptions.IgnoreCase);

        private static readonly Regex IpAddressRegex = new Regex(@"^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$", RegexOptions.IgnoreCase);

        private static readonly Regex EmailRegex = new Regex(@"^([\w-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([\w-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$", RegexOptions.IgnoreCase);
        private static readonly Regex EmailDomainRegex = new Regex(@"^@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([\w-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$", RegexOptions.IgnoreCase);

        private static readonly Regex TransactSqlRegex = new Regex(@"\?|select%20|select\s+|insert%20|insert\s+|delete%20|delete\s+|count\(|drop%20|drop\s+|update%20|update\s+", RegexOptions.IgnoreCase);

        private static readonly Regex NonColorCharRegex = new Regex(@"[^0-9a-f]", RegexOptions.IgnoreCase);

        private static readonly Regex Base64StringRegex = new Regex(@"[A-Za-z0-9\+\/\=]", RegexOptions.IgnoreCase);

        #endregion

        #region 正则表达式验证 Methods

        /// <summary>
        /// Indicates whether the specified string is email.
        /// </summary>
        /// <param name="str">The string to check.</param>
        /// <returns>true if the string is email, false otherwise.</returns>
        public static bool IsEmail(string str)
        {
            return EmailRegex.IsMatch(str);
        }

        /// <summary>
        /// Indicates whether the specified string is email domain.
        /// </summary>
        /// <param name="str">The string to check.</param>
        /// <returns>true if the string is email domain, false otherwise.</returns>
        public static bool IsEmailDomain(string str)
        {
            return EmailDomainRegex.IsMatch(str);
        }

        /// <summary>
        /// Indicates whether the specified string is transact-sql.
        /// </summary>
        /// <param name="str">The string to check.</param>
        /// <returns>true if the string is transact-sql, false otherwise.</returns>
        public static bool IsTransactSql(string str)
        {
            return TransactSqlRegex.IsMatch(str);
        }

        /// <summary>
        /// Indicates whether the specified string is 3/6 bit color.
        /// </summary>
        /// <param name="str">The string to check, #ffff00, fff e.g.</param>
        /// <returns>true if the string is 3/6 bit color, false otherwise.</returns>
        public static bool IsColor(string str)
        {
            if (str == null)
                return false;

            string color = str.Trim().Trim('#');
            // 长度为3或6且不包含0-9 a-f以外的字符
            if ((color.Length == 3 || color.Length == 6)
                && NonColorCharRegex.IsMatch(color) == false)
            {
                return true;
            }

            return false;
        }

        /// <summary>
        /// Indicates whether the specified char is chinese char.
        /// </summary>
        /// <param name="ch">The char to check</param>
        /// <returns>true if the char is chinese char, false otherwise.</returns>
        public static bool IsChineseChar(char ch)
        {
            byte[] bytes = BG2312Encoding.GetBytes(ch.ToString());
            if (bytes.Length == 2)
            {
                int zone = bytes[0]; //“区”值   
                int num = bytes[1]; //“位”值   

                return (zone >= 0xB0 && zone <= 0xF7) && (num > 0xA0 && num < 0xFD);
            }

            return false;
        }


        /// <summary>
        /// Indicates whether the specified string is in url format.
        /// </summary>
        /// <param name="url">A url string.</param>
        /// <returns>True if in url format, false otherwise.</returns>
        public static bool IsUrl(string url)
        {
            return UrlRegex.IsMatch(url);
        }

        /// <summary>
        /// Indicates whether the specified string is in ip format.
        /// </summary>
        /// <param name="ip">An ip string.</param>
        /// <returns>True if in ip format, false otherwise.</returns>
        public static bool IsIpAddress(string ip)
        {
            return IpAddressRegex.IsMatch(ip);
        }

        /// <summary>
        /// Indicates whether the specified string is a base64-encode string.
        /// </summary>
        /// <param name="str">The string to check.</param>
        /// <returns>true if the string is a base64-encode string, false otherwise.</returns>
        public static bool IsBase64String(string str)
        {
            //A-Z, a-z, 0-9, +, /, =
            return Base64StringRegex.IsMatch(str);
        }

        #endregion

        #region 时间格式处理
        #region Fields

        // Greenwich Mean Time
        private static readonly DateTime GmtDateTime = new DateTime(1970, 1, 1, 0, 0, 0, 0);
        private static readonly DateTime GmtDateTimeCn = new DateTime(1970, 1, 1, 8, 0, 0, 0);

        private static readonly string[] ShortDateFormats = new string[] { "yyyy-MM-dd", "yyyy-M-d" };

        private static readonly float[] ConstellationSpans = new float[] { 1.20F, 2.19F, 3.21F, 4.20F, 5.21F, 6.22F, 7.23F, 8.23F, 9.23F, 10.24F, 11.23F, 12.22F, 13.20F };
        private static readonly string[] ConstellationEnNames = new string[] { "Aquarius", "Pisces", "Aries", "Taurus", "Gemini", "Cancer", "Leo", "Virgo", "Libra", "Scorpion", "Sagittarius", "Capricorn" };
        private static readonly string[] ConstellationCnNames = new string[] { "水瓶座", "双鱼座", "白羊座", "金牛座", "双子座", "巨蟹座", "狮子座", "处女座", "天秤座", "天蝎座", "射手座", "魔羯座" };

        private static readonly string[] EnWeekNames = new string[] { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" };
        private static readonly string[] CnWeekNames = new string[] { "星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六" };
        private static readonly string[] EnMonthNames = new string[] { "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" };
        private static readonly string[] CnMonthNames = new string[] { "一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月" };

        #endregion

        #region Get Date String

        /// <summary>
        /// Gets the date time string in format "HH:mm:ss" of 
        /// DateTime.Now.
        /// </summary>
        /// <returns>The date time string</returns>
        public static string GetTime()
        {
            return GetTime(DateTime.Now);
        }

        /// <summary>
        /// Gets the date time string in format "HH:mm:ss" of 
        /// a specified date time.
        /// </summary>
        /// <param name="dateTime">Date time to get string from.</param>
        /// <returns>The date time string</returns>
        public static string GetTime(this DateTime dateTime)
        {
            return dateTime.ToString("HH:mm:ss");
        }

        /// <summary>
        /// Gets the date time string in format "yyyy-MM-dd" of 
        /// DateTime.Now.
        /// </summary>
        /// <returns>The date time string</returns>
        public static string GetDate()
        {
            return GetDate(DateTime.Now);
        }

        /// <summary>
        /// Gets the date time string in format "yyyy-MM-dd" of 
        /// a specified date time.
        /// </summary>
        /// <param name="dateTime">Date time to get string from.</param>
        /// <returns>The date time string</returns>
        public static string GetDate(this DateTime dateTime)
        {
            return dateTime.ToString("yyyy-MM-dd");
        }

        /// <summary>
        /// Gets the date time string in format "yyyy-MM-dd HH:mm:ss" of 
        /// DateTime.Now.
        /// </summary>
        /// <returns>The date time string</returns>
        public static string GetDateTime()
        {
            return GetDateTime(DateTime.Now);
        }

        /// <summary>
        /// Gets the date time string in format "yyyy-MM-dd HH:mm:ss" of 
        /// a specified date time.
        /// </summary>
        /// <param name="dateTime">Date time to get string from.</param>
        /// <returns>The date time string</returns>
        public static string GetDateTime(this DateTime dateTime)
        {
            return dateTime.ToString("yyyy-MM-dd HH:mm:ss");
        }

        /// <summary>
        /// Gets the standard date time string in format "yyyy-MM-dd HH:mm:ss:fffffff" of 
        /// DateTime.Now.
        /// </summary>
        /// <returns>The standard date time string</returns>
        public static string GetStandardDateTime()
        {
            return GetStandardDateTime(DateTime.Now);
        }

        /// <summary>
        /// Gets the standard date time string in format "yyyy-MM-dd HH:mm:ss:fffffff" of 
        /// a specified date time.
        /// </summary>
        /// <param name="dateTime">Date time to get string from.</param>
        /// <returns>The standard date time string</returns>
        public static string GetStandardDateTime(this DateTime dateTime)
        {
            return dateTime.ToString("yyyy-MM-dd HH:mm:ss:fffffff");
        }


        /// <summary>
        /// Gets a string describing the past time.
        /// </summary>
        /// <param name="date">The date time to calculate the past time.</param>
        /// <returns>A string describing the past time.</returns>
        public static string GetPastTimeExpression(this DateTime date)
        {
            return GetPastTimeExpression(date, false);
        }

        /// <summary>
        /// Gets a string describing the past time.
        /// </summary>
        /// <param name="date">The date time to calculate the past time.</param>
        /// <param name="brief">True to show briefly, otherwise false.</param>
        /// <returns>A string describing the past time.</returns>
        public static string GetPastTimeExpression(this DateTime date, bool brief)
        {
            DateTime now = DateTime.Now;
            double ts = System.Math.Abs((now - date).TotalSeconds);

            if (brief || date == DateTime.MinValue)
            {
                if (brief)
                {
                    if (now.Date == date.Date)
                        return "今天" + date.ToString("HH:mm");
                    else if (now.Date == date.AddDays(1).Date)
                        return "昨天" + date.ToString("HH:mm");
                    else
                        return string.Format("{0}月{1}日", date.Month, date.Day);
                }
                else
                {
                    if (ts <= (5 * 60))
                        return "刚刚";
                    else if (ts > (5 * 60) && ts <= (60 * 60))
                        return System.Math.Round(ts / 60) + "分钟前";
                    else if (ts > (60 * 60) && ts <= (24 * 60 * 60))
                        return System.Math.Round(ts / 3600) + "小时前";
                    else if (ts > (24 * 60 * 60) && ts <= (7 * 24 * 60 * 60))
                        return System.Math.Round(ts / 86400) + "天前";
                    else if (ts > (7 * 24 * 60 * 60) && ts <= (4 * 7 * 24 * 60 * 60))
                        return System.Math.Round(ts / 604800) + "星期前";
                    else
                        return date.ToString("yyyy-MM-dd hh:mm");
                }
            }
            else
            {
                if (brief)
                {
                    if (now.Date == date.Date)
                        return "Today" + date.ToString("HH:mm");
                    else if (now.Date == date.AddDays(1).Date)
                        return "Yesterday" + date.ToString("HH:mm");
                    else
                        return date.ToString("yyyy-MM-dd hh:mm");
                }
                else
                {
                    if (ts <= (5 * 60))
                        return "Right Now";
                    else if (ts > (5 * 60) && ts <= (60 * 60))
                        return System.Math.Round(ts / 60) + "Minutes Ago";
                    else if (ts > (60 * 60) && ts <= (24 * 60 * 60))
                        return System.Math.Round(ts / 3600) + "Hours Ago";
                    else if (ts > (24 * 60 * 60) && ts <= (7 * 24 * 60 * 60))
                        return System.Math.Round(ts / 86400) + "Days Ago";
                    else if (ts > (7 * 24 * 60 * 60) && ts <= (4 * 7 * 24 * 60 * 60))
                        return System.Math.Round(ts / 604800) + "Weeks Ago";
                    else
                        return date.ToString("yyyy-MM-dd hh:mm");
                }
            }
        }

        /// <summary>
        /// Gets the constellation name by a birthday.
        /// </summary>
        /// <param name="date">The date to get constellation from.</param>
        /// <returns>The constellation name.</returns>
        public static string GetConstellation(this DateTime date)
        {
            float dateF = 0.00F;
            int month = date.Month, day = date.Day;

            if (month == 1 && day < 20)
                dateF = float.Parse(string.Format("13.{0}", day.ToString().PadLeft(2, '0')));
            else
                dateF = float.Parse(string.Format("{0}.{1}", month, day.ToString().PadLeft(2, '0')));

            for (int i = 0, l = ConstellationSpans.Length - 1; i < l; ++i)
            {
                if (dateF >= ConstellationSpans[i] && dateF < ConstellationSpans[i + 1])
                    return ConstellationCnNames[i];
                //return Utils.InChinese ? ConstellationCnNames[i] : ConstellationEnNames[i];
            }

            return "Unknown Constellation";
        }

        #endregion

        #region IsShortDate/IsDateTime

        /// <summary>
        /// Gets a value that indicates whether the specified string is representation 
        /// of a date using format "yyyy-MM-dd" and "yyyy-M-d".
        /// </summary>
        /// <param name="str">A string containing a date and time.</param>
        /// <returns>True if the str parameter is representation of a date; otherwise, false.</returns>
        public static bool IsShortDate(string str)
        {
            return IsDateTime(str, ShortDateFormats);
        }

        /// <summary>
        /// Gets a value that indicates whether the specified string is representation 
        /// of a date and time.
        /// </summary>
        /// <param name="str">A string containing a date and time.</param>
        /// <returns>True if the str parameter is representation of a date and time; otherwise, false.</returns>
        public static bool IsDateTime(string str)
        {
            DateTime dt;
            return DateTime.TryParse(str, CultureInfo.InvariantCulture, DateTimeStyles.None, out dt);
        }

        /// <summary>
        /// Gets a value that indicates whether the specified string is representation 
        /// of a date and time using the specified format.
        /// </summary>
        /// <param name="str">A string containing a date and time.</param>
        /// <param name="format">The required format of str.</param>
        /// <returns>True if the str parameter is representation of a date and time; otherwise, false.</returns>
        public static bool IsDateTime(string str, string format)
        {
            DateTime dt;
            return DateTime.TryParseExact(str, format, CultureInfo.InvariantCulture, DateTimeStyles.None, out dt);
        }

        /// <summary>
        /// Gets a value that indicates whether the specified string is representation 
        /// of a date and time using the specified array of formats.
        /// </summary>
        /// <param name="str">A string containing a date and time.</param>
        /// <param name="formats">An array of allowable formats of str.</param>
        /// <returns>True if the str parameter is representation of a date and time; otherwise, false.</returns>
        public static bool IsDateTime(string str, string[] formats)
        {
            DateTime dt;
            return DateTime.TryParseExact(str, formats, CultureInfo.InvariantCulture, DateTimeStyles.None, out dt);
        }

        #endregion

        #region DateInterval/GetDateDiff/GetDateDiff(intervals)

        /// <summary>
        /// Indicates how to determine and format date intervals when calling date-related functions.
        /// </summary>
        public enum DateInterval
        {
            /// <summary>
            /// Year.
            /// </summary>
            Year,

            /// <summary>
            /// Month.
            /// </summary>
            Month,

            /// <summary>
            /// Week.
            /// </summary>
            Week,

            /// <summary>
            /// Day.
            /// </summary>
            Day,

            /// <summary>
            /// Hour.
            /// </summary>
            Hour,

            /// <summary>
            /// Minute.
            /// </summary>
            Minute,

            /// <summary>
            /// Second.
            /// </summary>
            Second,

            /// <summary>
            /// Millisecond.
            /// </summary>
            Millisecond
        }

        /// <summary>
        /// Gets a Long value specifying the number of time intervals between two Date values.
        /// </summary>
        /// <param name="interval">
        /// DateInterval enumeration value or String expression representing 
        /// the time interval you want to use as the unit of difference between Date1 and Date2.
        /// </param>
        /// <param name="startDate">The first date/time value you want to use in the calculation.</param>
        /// <param name="endDate">The second date/time value you want to use in the calculation.</param>
        /// <returns>Returns a Long value specifying the number of time intervals between two Date values.</returns>
        public static long GetDateDiff(DateInterval interval, DateTime startDate, DateTime endDate)
        {
            double val = 0D;
            TimeSpan ts = endDate - startDate;

            switch (interval)
            {
                case DateInterval.Year:
                    return endDate.Year - startDate.Year;
                case DateInterval.Month:
                    return (endDate.Month - startDate.Month) + (12 * (endDate.Year - startDate.Year));
                case DateInterval.Week:
                    val = ts.TotalDays / 7.0;
                    break;
                case DateInterval.Day:
                    val = ts.TotalDays;
                    break;
                case DateInterval.Hour:
                    val = ts.TotalHours;
                    break;
                case DateInterval.Minute:
                    val = ts.TotalMinutes;
                    break;
                case DateInterval.Second:
                    val = ts.TotalSeconds;
                    break;
                case DateInterval.Millisecond:
                    val = ts.TotalMilliseconds;
                    break;
                default:
                    throw new NotSupportedException("Not supported DatePart.");
            }

            return val > 0D ? (long)System.Math.Floor(val) : (long)System.Math.Ceiling(val);
        }

        /// <summary>
        /// Gets the total seconds of the time span of a specified date time and GMT date time.
        /// </summary>
        /// <param name="dateTime">A date time.</param>
        /// <returns>Total seconds of the time span.</returns>
        public static long GetGmtDateDiffSeconds(DateTime dateTime)
        {
            return GetDateDiff(DateInterval.Second, GmtDateTime, dateTime);
        }

        /// <summary>
        /// Gets a Long value specifying the number of year intervals between two Date values.
        /// </summary>
        /// <param name="startDate">The first date/time value you want to use in the calculation.</param>
        /// <param name="endDate">The second date/time value you want to use in the calculation.</param>
        /// <returns>Returns a Long value specifying the number of year intervals between two Date values.</returns>
        public static long GetDateDiffYears(DateTime startDate, DateTime endDate)
        {
            return GetDateDiff(DateInterval.Year, startDate, endDate);
        }

        /// <summary>
        /// Gets a Long value specifying the number of month intervals between two Date values.
        /// </summary>
        /// <param name="startDate">The first date/time value you want to use in the calculation.</param>
        /// <param name="endDate">The second date/time value you want to use in the calculation.</param>
        /// <returns>Returns a Long value specifying the number of month intervals between two Date values.</returns>
        public static long GetDateDiffMonths(DateTime startDate, DateTime endDate)
        {
            return GetDateDiff(DateInterval.Month, startDate, endDate);
        }

        /// <summary>
        /// Gets a Long value specifying the number of week intervals between two Date values.
        /// </summary>
        /// <param name="startDate">The first date/time value you want to use in the calculation.</param>
        /// <param name="endDate">The second date/time value you want to use in the calculation.</param>
        /// <returns>Returns a Long value specifying the number of week intervals between two Date values.</returns>
        public static long GetDateDiffWeeks(DateTime startDate, DateTime endDate)
        {
            return GetDateDiff(DateInterval.Week, startDate, endDate);
        }

        /// <summary>
        /// Gets a Long value specifying the number of day intervals between two Date values.
        /// </summary>
        /// <param name="startDate">The first date/time value you want to use in the calculation.</param>
        /// <param name="endDate">The second date/time value you want to use in the calculation.</param>
        /// <returns>Returns a Long value specifying the number of day intervals between two Date values.</returns>
        public static long GetDateDiffDays(DateTime startDate, DateTime endDate)
        {
            return GetDateDiff(DateInterval.Day, startDate, endDate);
        }

        /// <summary>
        /// Gets a Long value specifying the number of hour intervals between two Date values.
        /// </summary>
        /// <param name="startDate">The first date/time value you want to use in the calculation.</param>
        /// <param name="endDate">The second date/time value you want to use in the calculation.</param>
        /// <returns>Returns a Long value specifying the number of hour intervals between two Date values.</returns>
        public static long GetDateDiffHours(DateTime startDate, DateTime endDate)
        {
            return GetDateDiff(DateInterval.Hour, startDate, endDate);
        }

        /// <summary>
        /// Gets a Long value specifying the number of minute intervals between two Date values.
        /// </summary>
        /// <param name="startDate">The first date/time value you want to use in the calculation.</param>
        /// <param name="endDate">The second date/time value you want to use in the calculation.</param>
        /// <returns>Returns a Long value specifying the number of minute intervals between two Date values.</returns>
        public static long GetDateDiffMinutes(DateTime startDate, DateTime endDate)
        {
            return GetDateDiff(DateInterval.Minute, startDate, endDate);
        }

        /// <summary>
        /// Gets a Long value specifying the number of second intervals between two Date values.
        /// </summary>
        /// <param name="startDate">The first date/time value you want to use in the calculation.</param>
        /// <param name="endDate">The second date/time value you want to use in the calculation.</param>
        /// <returns>Returns a Long value specifying the number of second intervals between two Date values.</returns>
        public static long GetDateDiffSeconds(DateTime startDate, DateTime endDate)
        {
            return GetDateDiff(DateInterval.Second, startDate, endDate);
        }

        /// <summary>
        /// Gets a Long value specifying the number of millisecond intervals between two Date values.
        /// </summary>
        /// <param name="startDate">The first date/time value you want to use in the calculation.</param>
        /// <param name="endDate">The second date/time value you want to use in the calculation.</param>
        /// <returns>Returns a Long value specifying the number of millisecond intervals between two Date values.</returns>
        public static long GetDateDiffMilliseconds(DateTime startDate, DateTime endDate)
        {
            return GetDateDiff(DateInterval.Millisecond, startDate, endDate);
        }

        #endregion
        #endregion 时间格式处理

        #region Json格式数据处理
        /// <summary>
        /// Converts a string to json value with quote.
        /// </summary>
        /// <param name="str">The string to convert.</param>
        /// <returns>The converted josn value string.</returns>
        public static string StringToJsonValue(string str)
        {
            return StringToJsonValue(str, true);
        }

        /// <summary>
        /// Converts a string to json value.
        /// </summary>
        /// <param name="str">The string to convert.</param>
        /// <param name="withQuote">True if with quot, false otherwise.</param>
        /// <returns>The converted josn value string.</returns>
        public static string StringToJsonValue(string str, bool withQuote)
        {
            if (str == null || str.Length == 0)
                return "\"\"";

            int len = str.Length;
            StringBuilder sb = new StringBuilder(len + 4);

            if (withQuote)
                sb.Append('"');

            for (int i = 0; i < len; i++)
            {
                char c = str[i];
                switch (c)
                {
                    //case '\'':
                    //    sb.Append("\\\'");
                    //    break;
                    case '\"':
                        sb.Append("\\\"");
                        //sb.Append("\\&quot;");
                        break;
                    case '\\':
                        sb.Append("\\\\");
                        break;
                    //case '/':
                    //    sb.Append("\\/");
                    //    break;
                    case '\b':
                        sb.Append("\\b");
                        break;
                    case '\f':
                        sb.Append("\\f");
                        break;
                    case '\n':
                        sb.Append("\\n");
                        break;
                    case '\r':
                        sb.Append("\\r");
                        break;
                    case '\t':
                        sb.Append("\\t");
                        break;
                    default:
                        sb.Append(c);
                        break;
                }
            }

            if (withQuote)
                sb.Append('"');

            return sb.ToString();
        }


        /// <summary>
        /// Converts a .NET object to a string of Json.
        /// </summary>
        /// <param name="obj">Object to convert.</param>
        /// <returns>A json string represting the object parameter. The return value will be null of the object is null.</returns>
        public static string ObjectToJsonString(object obj)
        {
            return Serializer.ConvertToJsonString(obj);
        }

        /// <summary>
        /// Converts a string of Json to the supplied object type. 
        /// You will need to cast this object back to its expected type. 
        /// </summary>
        /// <param name="json">Json representing a .NET object.</param>
        /// <param name="type">The type of object which the Json represents.</param>
        /// <returns>A instance of object or null if the value of json is null or empty.</returns>
        public static object ObjectFromJsonString(string json, Type type)
        {
            return Serializer.ConvertFromJsonString(json, type);
        }

        /// <summary>
        /// Converts a string of Json to the supplied object type.
        /// </summary>
        /// <typeparam name="T">The type to return.</typeparam>
        /// <param name="json">Json representing a .NET object.</param>
        /// <returns>A instance of T or null if the value of json is null or empty.</returns>
        public static T ObjectFromJsonString<T>(string json)
        {
            return (T)Serializer.ConvertFromJsonString(json, typeof(T));
        }

        /// <summary>
        /// Produce a string in double quotes with backslash sequences in all the right places.
        /// </summary>
        /// <param name="str">A String</param>
        /// <returns>A String correctly formatted for insertion in a JSON message.</returns>
        private static string JsonEnquote(string str)
        {
            if (str == null || str.Length == 0)
                return "\"\"";

            int i, len = str.Length;
            StringBuilder sb = new StringBuilder(len + 4);
            string t;

            sb.Append('"');

            char c;
            for (i = 0; i < len; i += 1)
            {
                c = str[i];
                if ((c == '\\') || (c == '"') || (c == '>'))
                    sb.Append('\\').Append(c);
                else if (c == '\b')
                    sb.Append("\\b");
                else if (c == '\t')
                    sb.Append("\\t");
                else if (c == '\n')
                    sb.Append("\\n");
                else if (c == '\f')
                    sb.Append("\\f");
                else if (c == '\r')
                    sb.Append("\\r");
                else
                {
                    if (c < ' ')
                    {
                        t = "000" + int.Parse(new string(c, 1), NumberStyles.HexNumber);
                        sb.Append("\\u" + t.Substring(t.Length - 4));
                    }
                    else
                    {
                        sb.Append(c);
                    }
                }
            }
            sb.Append('"');

            return sb.ToString();
        }
        #endregion Json格式数据处理

        #region Encode/Decode

        /// <summary>
        /// Converts a string to html encode string.
        /// </summary>
        /// <param name="str">A string to encode.</param>
        /// <returns>The encoded string.</returns>
        public static string HtmlEncode(string str)
        {
            return string.IsNullOrEmpty(str) ? str : HttpUtility.HtmlEncode(str);
        }

        /// <summary>
        /// Converts a html encoded string to originally string.
        /// </summary>
        /// <param name="str">A string to decode.</param>
        /// <returns>The decoded string.</returns>
        public static string HtmlDecode(string str)
        {
            return string.IsNullOrEmpty(str) ? str : HttpUtility.HtmlDecode(str);
        }

        /// <summary>
        /// Converts a string to html attribute encode string.
        /// </summary>
        /// <param name="str">A string to encode.</param>
        /// <returns>The encoded string.</returns>
        public static string HtmlAttributeEncode(string str)
        {
            return string.IsNullOrEmpty(str) ? str : HttpUtility.HtmlAttributeEncode(str);
        }

        /// <summary>
        /// Encodes a url string.
        /// </summary>
        /// <param name="str">A url string to encode.</param>
        /// <returns>The encoded url.</returns>
        public static string UrlEncode(string str)
        {
            return string.IsNullOrEmpty(str) ? string.Empty : HttpUtility.UrlEncode(str);
        }

        /// <summary>
        /// Decodes a url string.
        /// </summary>
        /// <param name="str">A url string to decode.</param>
        /// <returns>The decoded url.</returns>
        public static string UrlDecode(string str)
        {
            return string.IsNullOrEmpty(str) ? string.Empty : HttpUtility.UrlDecode(str);
        }


        /// <summary>
        /// Converts a string to its equivalent string representation encoded with 
        /// base 64 digits using Encoding.UTF8.
        /// </summary>
        /// <param name="str">The string to convert.</param>
        /// <returns>The converted base64 string.</returns>
        public static string Base64Encode(string str)
        {
            return Base64Encode(str, Encoding.UTF8);
        }

        /// <summary>
        /// Converts a string to its equivalent string representation encoded with 
        /// base 64 digits.
        /// </summary>
        /// <param name="str">The string to convert.</param>
        /// <param name="encoding">Encoding of the string to get bytes.</param>
        /// <returns>The converted base64 string.</returns>
        public static string Base64Encode(string str, Encoding encoding)
        {
            if (string.IsNullOrEmpty(str))
                return string.Empty;

            return Convert.ToBase64String(encoding.GetBytes(str));
        }

        /// <summary>
        /// Converts the specified System.String, which encodes binary data as base 64 
        /// digits, to an equivalent string using Encoding.UTF8.
        /// </summary>
        /// <param name="str">The string to convert.</param>
        /// <returns>The converted string.</returns>
        public static string Base64Decode(string str)
        {
            return Base64Decode(str, Encoding.UTF8);
        }

        /// <summary>
        /// Converts the specified System.String, which encodes binary data as base 64 
        /// digits, to an equivalent string.
        /// </summary>
        /// <param name="str">The string to convert.</param>
        /// <param name="encoding">Encoding of the string to get bytes.</param>
        /// <returns>The converted string.</returns>
        public static string Base64Decode(string str, Encoding encoding)
        {
            if (string.IsNullOrEmpty(str))
                return string.Empty;

            return encoding.GetString(Convert.FromBase64String(str));
        }

        #endregion

        #region Encoding
        #endregion Encoding


        /// <summary>
        /// 
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        public static bool TypeAllowsNullValue(Type type)
        {
            // reference types allow null values
            if (!type.IsValueType)
            {
                return true;
            }

            // nullable value types allow null values
            // code lifted from System.Nullable.GetUnderlyingType()
            if (type.IsGenericType && !type.IsGenericTypeDefinition && (type.GetGenericTypeDefinition() == typeof(Nullable<>)))
            {
                return true;
            }

            // no other types allow null values
            return false;
        }

        #region GetCurrentlyBeingCalledMethod & GetCurrentlyCallingClassType

        /// <summary>
        /// Gets the currently-being-called method in currently-being-initialized class.
        /// </summary>
        /// <returns>The currently-being-called method in currently-being-initialized class.</returns>
        /// <remarks>This is a slow-running method. Make sure you're not doing this in a loop.</remarks>
        [MethodImpl(MethodImplOptions.NoInlining)]
        public static MethodBase GetCurrentlyBeingCalledMethod()
        {
            // StackTrace trace = new StackTrace();
            // 0 -> Current Class
            // 1 -> Calling Class
            // return (new StackTrace()).GetFrame(1).GetMethod();

            return (new StackFrame(1, false)).GetMethod();
        }

        /// <summary>
        /// Gets the <see cref="T:Type"/> of currently-being-initialized class.
        /// </summary>
        /// <returns>The <see cref="T:Type"/> of currently-being-initialized class.</returns>
        /// <remarks>This is a slow-running method. Make sure you're not doing this in a loop.</remarks>
        [MethodImpl(MethodImplOptions.NoInlining)]
        public static Type GetCurrentlyBeingInitializedClassType()
        {
            // StackTrace trace = new StackTrace();
            // 0 -> Current Class
            // 1 -> Calling Class
            // return (new StackTrace()).GetFrame(1).GetMethod().DeclaringType;

            return (new StackFrame(1, false)).GetMethod().DeclaringType;
        }

        #endregion

        #region GetRegistryValue/SetRegistryValue & GetEnvironmentVariable

        /// <summary>
        /// Retrieves the value associated with the specified name, in the specified 
        /// registry key. If the name is not found in the specified key, returns a default 
        /// value that you provide, or String.Empty if the specified key does not exist.
        /// </summary>
        /// <param name="keyName">
        /// The full registry path of the key, beginning with a valid registry root, 
        /// such as "HKEY_CURRENT_USER".
        /// </param>
        /// <param name="valueName">The name of the name/value pair.</param>
        /// <param name="defaultValue">The value to return if name does not exist.</param>
        /// <returns>
        /// String.Empty if the subkey specified by keyName does not exist; otherwise, the value 
        /// associated with valueName, or defaultValue if valueName is not found.
        /// </returns>
        public static string GetRegistryValue(string keyName, string valueName, object defaultValue)
        {
            try
            {
                object val = Registry.GetValue(keyName, valueName, defaultValue);
                return val == null ? string.Empty : val.ToString();
            }
            catch (Exception)
            {
                return string.Empty;
            }
        }

        /// <summary>
        /// Sets the specified name/value pair on the specified registry key. If the 
        /// specified key does not exist, it is created.
        /// </summary>
        /// <param name="keyName">
        /// The full registry path of the key, beginning with a valid registry root, 
        /// such as "HKEY_CURRENT_USER".
        /// </param>
        /// <param name="valueName">The name of the name/value pair.</param>
        /// <param name="value">The value to be stored.</param>
        public static void SetRegistryValue(string keyName, string valueName, object value)
        {
            try
            {
                Registry.SetValue(keyName, valueName, value);
            }
            catch (Exception)
            {
            }
        }

        /// <summary>
        /// Sets the name/value pair on the specified registry key, using the specified 
        /// registry data type. If the specified key does not exist, it is created.
        /// </summary>
        /// <param name="keyName">
        /// The full registry path of the key, beginning with a valid registry root, 
        /// such as "HKEY_CURRENT_USER".
        /// </param>
        /// <param name="valueName">The name of the name/value pair.</param>
        /// <param name="value">The value to be stored.</param>
        /// <param name="valueKind">The registry data type to use when storing the data.</param>
        public static void SetRegistryValue(string keyName, string valueName, object value, RegistryValueKind valueKind)
        {
            try
            {
                Registry.SetValue(keyName, valueName, value, valueKind);
            }
            catch (Exception)
            {
            }
        }

        /// <summary>
        /// Retrieves the value of an environment variable from the current process.
        /// </summary>
        /// <param name="variable">The name of the environment variable.</param>
        /// <returns>
        /// The value of the environment variable specified by variable, or string.Empty if the 
        /// environment variable is not found or the caller does not have the required permission 
        /// to perform this operation.
        /// </returns>
        public static string GetEnvironmentVariable(string variable)
        {
            try
            {
                string value = Environment.GetEnvironmentVariable(variable);
                return value == null ? string.Empty : value;
            }
            catch (System.Security.SecurityException)
            {
                return string.Empty;
            }
        }

        #endregion

         #region httppost
         /// <summary>
        /// Executes a http web request using "Post" method and returns the responsed string.
        /// </summary>
        /// <param name="url">The url to request.</param>
        /// <param name="postData">The data to be post.</param>
        /// <returns>The responsed string.</returns>
        public static string HttpPost(string url, string postData)
        {
            return HttpPost(url, postData, "gb2312", null);
        }

        /// <summary>
        /// Executes a http web request using "Post" method and returns the responsed string.
        /// </summary>
        /// <param name="url">The url to request.</param>
        /// <param name="postData">The data to be post.</param>
        /// <param name="encodingName">The encoding name.</param>
        /// <param name="referer">The referer url or let it empty.</param>
        /// <returns>The responsed string.</returns>
        public static string HttpPost(string url, string postData, string encodingName, string referer)
        {
            try
            {
                var request = (HttpWebRequest)HttpWebRequest.Create(url);

                var encoding = Encoding.GetEncoding(encodingName);
                var dataBytes = encoding.GetBytes(postData ?? string.Empty);
                //WebProxy myProxy = new WebProxy();
                //Uri newUri = new Uri("proxy.xxx.xxx:3128");
                //myProxy.Address = newUri;
                //request.Proxy = myProxy;
                request.AllowAutoRedirect = true;
                request.Timeout = 36000;
                request.Method = "POST";
                request.Headers["Cache-Control"] = "no-cache";
                request.Accept = "*/*";
                request.ContentType = "application/x-www-form-urlencoded";
                request.ContentLength = dataBytes.Length;
                request.UserAgent = "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0; SLCC1; .NET CLR 2.0.50727; InfoPath.2; .NET CLR 3.0.04506; .NET CLR 3.5.21022)";

                if (!string.IsNullOrEmpty(referer))
                {
                    request.Referer = referer;
                }

                using (var stream = request.GetRequestStream())
                {
                    stream.Write(dataBytes, 0, dataBytes.Length);
                    stream.Close();
                }

                using (var response = (HttpWebResponse)request.GetResponse())
                {
                    var stream = response.GetResponseStream();


                    using (var reader = new StreamReader(stream, System.Text.Encoding.GetEncoding("gb2312")))
                    {
                        string content = reader.ReadToEnd();

                        return content;
                    }
                }
            }
            catch (Exception ex)
            {                

                return ex.Message;
            }
        }
          #endregion httppost
    }
}
